您的位置:首页 > 其它

Memory leak in backtrace call?

2013-10-16 12:07 344 查看



http://www.linuxquestions.org/questions/linux-general-1/does-the-backtrace-call-lost-memory-837435/

Here is a test code for memory alloc and free. It is to detect whether the allocs and frees match. From the result, after backtrace call, there is some memory alloc, but it does not free these memories after calling or the process exit. Why? Nomorlly, the memory
alloced need to be freed after use, or the memory will leak.

But I run this program for about some times, and find that though the system memory does not real leak,the free memory decreases, and the cache increases(Use free command).

[root@localhost memory]# free

total used free shared buffers cached

Mem: 945944 749488 196456 0 87952 501112

-/+ buffers/cache: 160424 785520

Swap: 1900536 0 1900536

[root@localhost memory]# free

total used free shared buffers cached

Mem: 945944 751384 194560 0 87960 501936

-/+ buffers/cache: 161488 784456

Swap: 1900536 0 1900536

And use valgrind to detect memory, it doesnot find leak. See the valgrind bellow.

#include <execinfo.h>

#include <stdio.h>

#include <stdlib.h>

#include <malloc.h>

static void* (* old_malloc_hook)(size_t,const void*);

static void (* old_free_hook)(void*,const void*);

static void my_init_hook(void);

static void* my_malloc_hook(size_t,const void*);

static void my_free_hook(void*,const void*);

static void my_init_hook(void)

{

old_malloc_hook=__malloc_hook;

old_free_hook=__free_hook;

__malloc_hook=my_malloc_hook;

__free_hook=my_free_hook;

}

static void* my_malloc_hook(size_t size,const void* caller)

{

void *array[10];

size_t size1;

void *result;

__malloc_hook=old_malloc_hook;

__free_hook=my_free_hook;

result=malloc(size);

__malloc_hook=my_malloc_hook;

printf("@@@ %p + %p 0x%x\n",caller,result,(unsigned long int)size);

return result;

}

static void my_free_hook(void* ptr,const void* caller)

{

__free_hook=old_free_hook;

free(ptr);

old_free_hook=__free_hook;

printf("@@@ %p - %p\n",caller,ptr);

__free_hook=my_free_hook;

}

/* Obtain a backtrace and print it to stdout. */

void print_trace (void)

{

void *array[10];

size_t size;

char **strings;

size_t i;

size = backtrace (array, 10);

}

/* A dummy function to make the backtrace more interesting. */

void dummy_function (void)

{

print_trace ();

}

int main (void)

{

my_init_hook();

dummy_function ();

return 0;

}

Valgrind results:

[root@localhost memory]# valgrind --tool=memcheck --leak-check=full --show-reachable=yes ./test2

==4018== Memcheck, a memory error detector.

==4018== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al.

==4018== Using LibVEX rev 1658, a library for dynamic binary translation.

==4018== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.

==4018== Using valgrind-3.2.1, a dynamic binary instrumentation framework.

==4018== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.

==4018== For more details, rerun with: -v

==4018==

==4018==

==4018== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 1)

==4018== malloc/free: in use at exit: 904 bytes in 5 blocks.

==4018== malloc/free: 5 allocs, 0 frees, 904 bytes allocated.

==4018== For counts of detected errors, rerun with: -v

==4018== searching for pointers to 5 not-freed blocks.

==4018== checked 52,300 bytes.

==4018==

==4018== 19 bytes in 1 blocks are still reachable in loss record 1 of 5

==4018== at 0x40053C0: malloc (vg_replace_malloc.c:149)

==4018== by 0x4F389724: _dl_new_object (in /lib/ld-2.5.so)

==4018== by 0x4F385020: _dl_map_object_from_fd (in /lib/ld-2.5.so)

==4018== by 0x4F387333: _dl_map_object (in /lib/ld-2.5.so)

==4018== by 0x4F3905B8: dl_open_worker (in /lib/ld-2.5.so)

==4018== by 0x4F38CB45: _dl_catch_error (in /lib/ld-2.5.so)

==4018== by 0x4F3900D1: _dl_open (in /lib/ld-2.5.so)

==4018== by 0x4F4A34A1: do_dlopen (in /lib/libc-2.5.so)

==4018== by 0x4F38CB45: _dl_catch_error (in /lib/ld-2.5.so)

==4018== by 0x4F4A3654: __libc_dlopen_mode (in /lib/libc-2.5.so)

==4018== by 0x4F480FD8: init (in /lib/libc-2.5.so)

==4018== by 0x4F481172: backtrace (in /lib/libc-2.5.so)

==4018==

==4018==

==4018== 19 bytes in 1 blocks are still reachable in loss record 2 of 5

==4018== at 0x40053C0: malloc (vg_replace_malloc.c:149)

==4018== by 0x4F387883: _dl_map_object (in /lib/ld-2.5.so)

==4018== by 0x4F3905B8: dl_open_worker (in /lib/ld-2.5.so)

==4018== by 0x4F38CB45: _dl_catch_error (in /lib/ld-2.5.so)

==4018== by 0x4F3900D1: _dl_open (in /lib/ld-2.5.so)

==4018== by 0x4F4A34A1: do_dlopen (in /lib/libc-2.5.so)

==4018== by 0x4F38CB45: _dl_catch_error (in /lib/ld-2.5.so)

==4018== by 0x4F4A3654: __libc_dlopen_mode (in /lib/libc-2.5.so)

==4018== by 0x4F480FD8: init (in /lib/libc-2.5.so)

==4018== by 0x4F481172: backtrace (in /lib/libc-2.5.so)

==4018== by 0x8048596: print_trace (in /root/memory/test2)

==4018== by 0x80485A6: dummy_function (in /root/memory/test2)

==4018==

==4018==

==4018== 28 bytes in 1 blocks are still reachable in loss record 3 of 5

==4018== at 0x40053C0: malloc (vg_replace_malloc.c:149)

==4018== by 0x4F38B978: _dl_map_object_deps (in /lib/ld-2.5.so)

==4018== by 0x4F390614: dl_open_worker (in /lib/ld-2.5.so)

==4018== by 0x4F38CB45: _dl_catch_error (in /lib/ld-2.5.so)

==4018== by 0x4F3900D1: _dl_open (in /lib/ld-2.5.so)

==4018== by 0x4F4A34A1: do_dlopen (in /lib/libc-2.5.so)

==4018== by 0x4F38CB45: _dl_catch_error (in /lib/ld-2.5.so)

==4018== by 0x4F4A3654: __libc_dlopen_mode (in /lib/libc-2.5.so)

==4018== by 0x4F480FD8: init (in /lib/libc-2.5.so)

==4018== by 0x4F481172: backtrace (in /lib/libc-2.5.so)

==4018== by 0x8048596: print_trace (in /root/memory/test2)

==4018== by 0x80485A6: dummy_function (in /root/memory/test2)

==4018==

==4018==

==4018== 224 bytes in 1 blocks are still reachable in loss record 4 of 5

==4018== at 0x40046FF: calloc (vg_replace_malloc.c:279)

==4018== by 0x4F38E293: _dl_check_map_versions (in /lib/ld-2.5.so)

==4018== by 0x4F3908D0: dl_open_worker (in /lib/ld-2.5.so)

==4018== by 0x4F38CB45: _dl_catch_error (in /lib/ld-2.5.so)

==4018== by 0x4F3900D1: _dl_open (in /lib/ld-2.5.so)

==4018== by 0x4F4A34A1: do_dlopen (in /lib/libc-2.5.so)

==4018== by 0x4F38CB45: _dl_catch_error (in /lib/ld-2.5.so)

==4018== by 0x4F4A3654: __libc_dlopen_mode (in /lib/libc-2.5.so)

==4018== by 0x4F480FD8: init (in /lib/libc-2.5.so)

==4018== by 0x4F481172: backtrace (in /lib/libc-2.5.so)

==4018== by 0x8048596: print_trace (in /root/memory/test2)

==4018== by 0x80485A6: dummy_function (in /root/memory/test2)

==4018==

==4018==

==4018== 614 bytes in 1 blocks are still reachable in loss record 5 of 5

==4018== at 0x40046FF: calloc (vg_replace_malloc.c:279)

==4018== by 0x4F3894BA: _dl_new_object (in /lib/ld-2.5.so)

==4018== by 0x4F385020: _dl_map_object_from_fd (in /lib/ld-2.5.so)

==4018== by 0x4F387333: _dl_map_object (in /lib/ld-2.5.so)

==4018== by 0x4F3905B8: dl_open_worker (in /lib/ld-2.5.so)

==4018== by 0x4F38CB45: _dl_catch_error (in /lib/ld-2.5.so)

==4018== by 0x4F3900D1: _dl_open (in /lib/ld-2.5.so)

==4018== by 0x4F4A34A1: do_dlopen (in /lib/libc-2.5.so)

==4018== by 0x4F38CB45: _dl_catch_error (in /lib/ld-2.5.so)

==4018== by 0x4F4A3654: __libc_dlopen_mode (in /lib/libc-2.5.so)

==4018== by 0x4F480FD8: init (in /lib/libc-2.5.so)

==4018== by 0x4F481172: backtrace (in /lib/libc-2.5.so)

==4018==

==4018== LEAK SUMMARY:

==4018== definitely lost: 0 bytes in 0 blocks.

==4018== possibly lost: 0 bytes in 0 blocks.

==4018== still reachable: 904 bytes in 5 blocks.

==4018== suppressed: 0 bytes in 0 blocks.

Can somebody explain this? Whether the backtrace call really memory leak?

Thanks,

L.

=====================================================================

Here is a test code for memory alloc and free. It is to detect whether the allocs and frees match. From the result, after backtrace call, there is some memory alloc, but it does not free these memories after calling or the process exit. Why? Nomorlly, the memory
alloced need to be freed after use, or the memory will leak.

This statement is only true within a single process. In that context one needs to free the memory so that it can be reused. However, all this activity is unseen by the kernel; when the process terminates, the kernel recovers it all.

You have not leaked memory so long as the cache + used + free remains constant. A leak would show as a decrease in the amount of memory that the kernel controls.

It's not unusual for these numbers to jitter a great deal -- the memory management inside the kernel is constantly reoptimizing.

=====================================================================

Thank you very much for your explaination.

I did more tests, all the memory alloced will be returned to OS after the process exit without "free" operations.

But I am still confused why these memories the backtrace alloced are not returned to OS after backtrace is called? Is this a memory leak for the process during its running status?

=====================================================================

Add some information to this qustion descrition:

1. Every time run this test program, it will alloc memories for 5 times, like this:

@@@ 0xb7869c6f + 0x804b008 0x13

@@@ 0xb786f0bb + 0x804b020 0x272

@@@ 0xb786f345 + 0x804b298 0x13

@@@ 0xb7871ca7 + 0x804b2b0 0x1c

@@@ 0xb7874dee + 0x804b2d0 0xe0

2. If the backtrace is called more than 2 times, it will not alloc memory after 1st call.

3. Tracing in the backtrace, find that the memories are alloced by init() function in it. Following is the details with gcc-2.9:

((gdb) n

3546 return (*hook)(bytes, RETURN_ADDRESS (0));

(gdb) n

@@@ 0xb7fe4c6f + 0x804b008 0x13

3576 }

(gdb) bt

#0 *__GI___libc_malloc (bytes=19) at malloc.c:3576

#1 0xb7fe4c6f in local_strdup (s=0xb7e3e52f "/lib/libgcc_s.so.1")

at dl-load.c:170

#2 0xb7fe7b0c in _dl_map_object (loader=0xb7fff668,

name=0xb7f790f9 "libgcc_s.so.1", preloaded=0, type=2, trace_mode=0,

mode=-1879048191, nsid=0) at dl-load.c:2150

#3 0xb7ff25e7 in dl_open_worker (a=0xbffff330) at dl-open.c:293

#4 0xb7fee356 in _dl_catch_error (objname=0xbffff358, errstring=0xbffff354,

mallocedp=0xbffff35f, operate=0xb7ff24a0 <dl_open_worker>, args=0xbffff330)

at dl-error.c:178

#5 0xb7ff1fee in _dl_open (file=0xb7f790f9 "libgcc_s.so.1", mode=-2147483647,

caller_dlopen=0x0, nsid=-2, argc=1, argv=0xbffff614, env=0xbffff61c)

at dl-open.c:596

#6 0xb7f5bfe2 in do_dlopen (ptr=0xbffff4b0) at dl-libc.c:86

#7 0xb7fee356 in _dl_catch_error (objname=0xbffff48c, errstring=0xbffff488,

mallocedp=0xbffff493, operate=0xb7f5bf80 <do_dlopen>, args=0xbffff4b0)

at dl-error.c:178

#8 0xb7f5c0e1 in dlerror_run (operate=<value optimized out>,

args=<value optimized out>) at dl-libc.c:47

#9 0xb7f5c206 in *__GI___libc_dlopen_mode (name=0x0, mode=-2147483647)

at dl-libc.c:160

#10 0xb7f379f8 in init () at ../sysdeps/i386/backtrace.c:44

#11 0xb7f37b8d in *__GI___backtrace (array=0xbffff524, size=10)

---Type <return> to continue, or q <return> to quit---

at ../sysdeps/i386/backtrace.c:121

#12 0x0804861d in print_trace () at test.c:50

#13 0x0804862d in dummy_function () at test.c:57

#14 0x0804864a in main () at test.c:63

(gdb)

##############################################################

(gdb) n

2242 return _dl_map_object_from_fd (name, fd, &fb, realname, loader, type, mode,

(gdb) n

@@@ 0xb7fea0bb + 0x804b020 0x272

@@@ 0xb7fea345 + 0x804b298 0x13

2244 }

(gdb) bt

#0 _dl_map_object (loader=0x0, name=0xb7f790f9 "libgcc_s.so.1", preloaded=0,

type=2, trace_mode=0, mode=-1879048191, nsid=0) at dl-load.c:2244

#1 0xb7ff25e7 in dl_open_worker (a=0xbffff330) at dl-open.c:293

#2 0xb7fee356 in _dl_catch_error (objname=0xbffff358, errstring=0xbffff354,

mallocedp=0xbffff35f, operate=0xb7ff24a0 <dl_open_worker>, args=0xbffff330)

at dl-error.c:178

#3 0xb7ff1fee in _dl_open (file=0xb7f790f9 "libgcc_s.so.1", mode=-2147483647,

caller_dlopen=0x0, nsid=-2, argc=1, argv=0xbffff614, env=0xbffff61c)

at dl-open.c:596

#4 0xb7f5bfe2 in do_dlopen (ptr=0xbffff4b0) at dl-libc.c:86

#5 0xb7fee356 in _dl_catch_error (objname=0xbffff48c, errstring=0xbffff488,

mallocedp=0xbffff493, operate=0xb7f5bf80 <do_dlopen>, args=0xbffff4b0)

at dl-error.c:178

#6 0xb7f5c0e1 in dlerror_run (operate=<value optimized out>,

args=<value optimized out>) at dl-libc.c:47

#7 0xb7f5c206 in *__GI___libc_dlopen_mode (name=0xb7fd04a4 "a",

mode=-2147483647) at dl-libc.c:160

#8 0xb7f379f8 in init () at ../sysdeps/i386/backtrace.c:44

#9 0xb7f37b8d in *__GI___backtrace (array=0xbffff524, size=10)

at ../sysdeps/i386/backtrace.c:121

#10 0x0804861d in print_trace () at test.c:50

#11 0x0804862d in dummy_function () at test.c:57

#12 0x0804864a in main () at test.c:63

(gdb)

##############################################################

330 _dl_map_object_deps (new, NULL, 0, 0,

(gdb) n

@@@ 0xb7fecca7 + 0x804b2b0 0x1c

334 for (i = 0; i < new->l_searchlist.r_nlist; ++i)

(gdb) bt

#0 dl_open_worker (a=0xbffff330) at dl-open.c:334

#1 0xb7fee356 in _dl_catch_error (objname=0xbffff358, errstring=0xbffff354,

mallocedp=0xbffff35f, operate=0xb7ff24a0 <dl_open_worker>, args=0xbffff330)

at dl-error.c:178

#2 0xb7ff1fee in _dl_open (file=0xb7f790f9 "libgcc_s.so.1", mode=-2147483647,

caller_dlopen=0x0, nsid=-2, argc=1, argv=0xbffff614, env=0xbffff61c)

at dl-open.c:596

#3 0xb7f5bfe2 in do_dlopen (ptr=0xbffff4b0) at dl-libc.c:86

#4 0xb7fee356 in _dl_catch_error (objname=0xbffff48c, errstring=0xbffff488,

mallocedp=0xbffff493, operate=0xb7f5bf80 <do_dlopen>, args=0xbffff4b0)

at dl-error.c:178

#5 0xb7f5c0e1 in dlerror_run (operate=<value optimized out>,

args=<value optimized out>) at dl-libc.c:47

#6 0xb7f5c206 in *__GI___libc_dlopen_mode (name=0x0, mode=-2147483647)

at dl-libc.c:160

#7 0xb7f379f8 in init () at ../sysdeps/i386/backtrace.c:44

#8 0xb7f37b8d in *__GI___backtrace (array=0xbffff524, size=10)

at ../sysdeps/i386/backtrace.c:121

#9 0x0804861d in print_trace () at test.c:50

#10 0x0804862d in dummy_function () at test.c:57

#11 0x0804864a in main () at test.c:63

(gdb)

##############################################################

(gdb) n

336 (void) _dl_check_map_versions (new->l_searchlist.r_list[i]->l_real,

(gdb) n

@@@ 0xb7fefdee + 0x804b2d0 0xe0

334 for (i = 0; i < new->l_searchlist.r_nlist; ++i)

(gdb) bt

#0 dl_open_worker (a=0xbffff330) at dl-open.c:334

#1 0xb7fee356 in _dl_catch_error (objname=0xbffff358, errstring=0xbffff354,

mallocedp=0xbffff35f, operate=0xb7ff24a0 <dl_open_worker>, args=0xbffff330)

at dl-error.c:178

#2 0xb7ff1fee in _dl_open (file=0xb7f790f9 "libgcc_s.so.1", mode=-2147483647,

caller_dlopen=0x0, nsid=-2, argc=1, argv=0xbffff614, env=0xbffff61c)

at dl-open.c:596

#3 0xb7f5bfe2 in do_dlopen (ptr=0xbffff4b0) at dl-libc.c:86

#4 0xb7fee356 in _dl_catch_error (objname=0xbffff48c, errstring=0xbffff488,

mallocedp=0xbffff493, operate=0xb7f5bf80 <do_dlopen>, args=0xbffff4b0)

at dl-error.c:178

#5 0xb7f5c0e1 in dlerror_run (operate=<value optimized out>,

args=<value optimized out>) at dl-libc.c:47

#6 0xb7f5c206 in *__GI___libc_dlopen_mode (name=0x804b020 "",

mode=-2147483647) at dl-libc.c:160

#7 0xb7f379f8 in init () at ../sysdeps/i386/backtrace.c:44

#8 0xb7f37b8d in *__GI___backtrace (array=0xbffff524, size=10)

at ../sysdeps/i386/backtrace.c:121

#9 0x0804861d in print_trace () at test.c:50

#10 0x0804862d in dummy_function () at test.c:57

#11 0x0804864a in main () at test.c:63

(gdb)

=====================================================================

To be continued and concluded

=====================================================================

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: