Donnerstag, 12. September 2013

False Alarm While Checking For Memory Leaks in GLib2 Hashmaps

After I finished a complex implementation using GLib2 hash tables the memory checker valgrind reported several memory leaks. Spending some time to track down the issue it all came down to the following supposingly problematic code:
int main() {
    GHashTable* item = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, g_free );
    g_hash_table_insert( item, g_strdup("key") , g_strdup("value") );
    g_hash_table_destroy( item );
}
Valgrind complained about 1512 lost bytes:
valgrind --leak-check=full ./hash.out

==12624== Memcheck, a memory error detector
==12624== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==12624== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==12624== Command: ./hash.out
==12624== 
==12624== 
==12624== HEAP SUMMARY:
==12624==     in use at exit: 5,656 bytes in 12 blocks
==12624==   total heap usage: 17 allocs, 5 frees, 5,758 bytes allocated
==12624== 
==12624== 1,512 bytes in 3 blocks are possibly lost in loss record 9 of 10
==12624==    at 0x402A420: memalign (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==12624==    by 0x402A4DE: posix_memalign (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==12624==    by 0x40592E1: ??? (in /lib/i386-linux-gnu/libglib-2.0.so.0.3200.3)
==12624==    by 0x40A573F: g_slice_alloc (in /lib/i386-linux-gnu/libglib-2.0.so.0.3200.3)
==12624==    by 0x4079EB1: g_hash_table_new_full (in /lib/i386-linux-gnu/libglib-2.0.so.0.3200.3)
==12624==    by 0x804883D: main (in /home/xubuntu/projects/playing_with_glib2/hash.out)
==12624== 
==12624== LEAK SUMMARY:
==12624==    definitely lost: 0 bytes in 0 blocks
==12624==    indirectly lost: 0 bytes in 0 blocks
==12624==      possibly lost: 1,512 bytes in 3 blocks
==12624==    still reachable: 4,144 bytes in 9 blocks
==12624==         suppressed: 0 bytes in 0 blocks
==12624== Reachable blocks (those to which a pointer was found) are not shown.
==12624== To see them, rerun with: --leak-check=full --show-reachable=yes
==12624== 
==12624== For counts of detected and suppressed errors, rerun with: -v
==12624== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

After intensive trying and eventually searching your favorite search engine it turned out, that newer (including mine) version of GLib2 are using by default a mechanism to allocate memory which leads to false alarms within valgrind, even if the hash table is destroyed correctly after usage.

To overcome this by setting the two environment variables G_SLICE and G_DEBUG before calling valgrind. Read more here and here.

With this test configuration valgrind is satisfied:
G_SLICE=always-malloc G_DEBUG=gc-friendly valgrind --leak-check=full ./hash.out 

==12671== Memcheck, a memory error detector
==12671== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==12671== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==12671== Command: ./hash.out
==12671== 
==12671== 
==12671== HEAP SUMMARY:
==12671==     in use at exit: 2,116 bytes in 5 blocks
==12671==   total heap usage: 11 allocs, 6 frees, 2,274 bytes allocated
==12671== 
==12671== LEAK SUMMARY:
==12671==    definitely lost: 0 bytes in 0 blocks
==12671==    indirectly lost: 0 bytes in 0 blocks
==12671==      possibly lost: 0 bytes in 0 blocks
==12671==    still reachable: 2,116 bytes in 5 blocks
==12671==         suppressed: 0 bytes in 0 blocks
==12671== Reachable blocks (those to which a pointer was found) are not shown.
==12671== To see them, rerun with: --leak-check=full --show-reachable=yes
==12671== 
==12671== For counts of detected and suppressed errors, rerun with: -v
==12671== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Keine Kommentare:

Kommentar veröffentlichen