LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices


Reply
  Search this Thread
Old 10-11-2010, 11:53 AM   #1
lagignition
LQ Newbie
 
Registered: Oct 2010
Distribution: Suse, Redhat
Posts: 3

Rep: Reputation: 0
Does the backtrace call lost memory?


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.I
 
Old 10-16-2010, 02:46 PM   #2
4dummies
LQ Newbie
 
Registered: May 2009
Location: Central coast of California.
Distribution: Xubuntu
Posts: 21

Rep: Reputation: 2
Smile

> 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.
 
1 members found this post helpful.
Old 10-19-2010, 03:42 AM   #3
lagignition
LQ Newbie
 
Registered: Oct 2010
Distribution: Suse, Redhat
Posts: 3

Original Poster
Rep: Reputation: 0
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?



Quote:
Originally Posted by 4dummies View Post
> 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.
 
Old 10-20-2010, 02:27 AM   #4
lagignition
LQ Newbie
 
Registered: Oct 2010
Distribution: Suse, Redhat
Posts: 3

Original Poster
Rep: Reputation: 0
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:

[I]((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->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)

Last edited by lagignition; 10-20-2010 at 03:13 AM. Reason: More correct debug information
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Call Stack Memory Management pseudosig Linux - Kernel 6 10-03-2008 12:03 PM
System call to get current process memory usage? mattengland Programming 4 03-15-2006 07:07 PM
Tough problem: Cannot allocate memory for a simple cp call! svar Linux - General 3 01-07-2006 08:24 AM
Tough problem: Cannot allocate memory for a simple cp call! svar Linux - General 4 01-06-2006 10:48 AM
lost memory pauloco Linux - Hardware 3 09-21-2004 09:39 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - General

All times are GMT -5. The time now is 08:44 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration