Re: Glib hashtable memory leak
- From: "Ovidiu Gheorghies" <ogheorghies gmail com>
- To: gtk-list gnome org
- Subject: Re: Glib hashtable memory leak
- Date: Fri, 2 May 2008 12:36:23 +0300
Hello all,
Thanks for the feedback, and I will summarize the "howto" on this. I believe the same memory leakage reporting issue is being discussed in
the thread "checking for memory leaks in gtk". I am ok with Glib not
explicitly freeing some singletons on exit, but the real issue is to
distinguish genuine leaks in user code from "leaks" that are
attributable to Glib.
First, the problem. When the `G_' macros are defined, less memory is reported as leaked, but some still remains unaccounted for according to mtrace. See the comparison below:
$ cat test1.c
#include <glib.h>
#include <mcheck.h>
int main()
{
mtrace();
GHashTable* hash_table;
hash_table=g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_unref (hash_table);
return 1;
}
$ gcc test1.c -o test1 -I/usr/include/glib-2.0/ -I/usr/lib64/glib-2.0/include/ -lglib-2.0
$ export MALLOC_TRACE=0.mtrace.log
$ ./test1; mtrace ./test1 $MALLOC_TRACE
Memory not freed:
-----------------
Address Size Caller
0x0000000000601460 0x1f8 at 0x3fea834002
0x0000000000601660 0xfc at 0x3fea834002
0x0000000000601770 0x1f8 at 0x3fea834002
0x0000000000601970 0x7f0 at 0x3fea834002
0x0000000000602400 0x3f0 at 0x3fea8423e1
0x0000000000602800 0x3f0 at 0x3fea8423e1
Now, when the G_ macros are defined, less memory is reported as leaked.
$ export G_DEBUG=gc-friendly
$ export G_SLICE=always-malloc
$ ./test1; mtrace ./test1 $MALLOC_TRACE
Memory not freed:
-----------------
Address Size Caller
0x0000000000601460 0x1f8 at 0x3fea834002
0x0000000000601660 0xfc at 0x3fea834002
0x0000000000601770 0x1f8 at 0x3fea834002
Simple cases such as:
malloc(20);
GHashTable* hash_table;
hash_table=g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_unref (hash_table);
can be easily caught by adding the -g option when compiling:
$ gcc -g test1.c -o test1 -I/usr/include/glib-2.0/ -I/usr/lib64/glib-2.0/include/ -lglib-2.0
$ ./test1; mtrace ./test1 $MALLOC_TRACE
Memory not freed:
-----------------
Address Size Caller
0x0000000000601460 0x14 at /home/user/devel/linux/glib/test1.c:13 <-------- obviously, your code does not free allocated memory
0x0000000000601480 0x1f8 at 0x3fea834002
0x0000000000601680 0xfc at 0x3fea834002
0x0000000000601790 0x1f8 at 0x3fea834002
But when leaks are related to not using glib properly, such as not calling unref, things are more difficult to diagnose:
GHashTable* hash_table;
hash_table=g_hash_table_new(g_str_hash, g_str_equal);
$ gcc -g test1.c -o test1 -I/usr/include/glib-2.0/ -I/usr/lib64/glib-2.0/include/ -lglib-2.0
$ ./test1; mtrace ./test1 $MALLOC_TRACE
Memory not freed:
-----------------
Address Size Caller
0x0000000000601460 0x1f8 at 0x3fea834002
0x0000000000601660 0xfc at 0x3fea834002
0x0000000000601770 0x1f8 at 0x3fea834002
0x0000000000601970 0x38 at 0x3fea83407b
0x00000000006019b0 0x58 at 0x3fea834002 <----------- Is there an memory allocation error? If yes, where and why?
With valgrind, the diagnostics is much better though (note the --leak-check=full option for valgrind and the -g option for gcc):
$ G_SLICE=always-malloc G_DEBUG=gc-friendly valgrind --tool=memcheck --leak-check=full ./test1
--- some lines cut out
==4071== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 1)
==4071== malloc/free: in use at exit: 2,484 bytes in 7 blocks.
==4071== malloc/free: 7 allocs, 0 frees, 2,484 bytes allocated.
==4071== For counts of detected errors, rerun with: -v
==4071== searching for pointers to 7 not-freed blocks.
==4071== checked 74,704 bytes.
==4071==
==4071== 144 (56 direct, 88 indirect) bytes in 1 blocks are definitely lost in loss record 1 of 5
==4071== at 0x4A05996: malloc (vg_replace_malloc.c:149)
==4071== by 0x3FEA83407A: g_malloc (in /lib64/libglib-2.0.so.0.1200.13)
==4071== by 0x3FEA820CF2: g_hash_table_new_full (in /lib64/libglib-2.0.so.0.1200.13)
==4071== by 0x4005E3: main (test1.c:13) <----------------------------------------------------------- AHA! there's the culprit
--- some lines cut out
And when the leak is fixed (add an unref call to the code above), the valgrind output looks better:
==4105== LEAK SUMMARY:
==4105== definitely lost: 0 bytes in 0 blocks.
==4105== possibly lost: 0 bytes in 0 blocks.
==4105== still reachable: 2,340 bytes in 5 blocks.
==4105== suppressed: 0 bytes in 0 blocks.
So I think this pretty much solves my issue of checking for memory leaks with glib, many thanks for your help.
Regards,
Ovidiu
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]