It is getting more and more frustrating that I need to work with C
functions where GLIB
ones makes my life harder.
I do use suppression file to drop those false responses from valgrind
, but the question still remains, why happens in some cases where in my opinion should not, strange results?
The cases which I am talking about are if I am calling g_print()
after return
in void functions.
The following program explains the situation:
#include <stdio.h>
#include <glib.h>
struct node
{
int property;
char name;
char type;
struct node *next;
};
struct node *createList ( const int val );
struct node *addNode ( const int val );
void freeList ( struct node *head );
int main ( void )
{
int n_lists = 5;
struct node *head = createList ( n_lists );
( void ) head;
freeList ( NULL );
}
struct node *createList ( const int val )
{
struct node *node = NULL;
struct node *current = node;
for ( int i = val ; i > 0 ; i-- )
{
current = addNode ( i );
if ( current == NULL )
{
return NULL;
}
current->next = node;
node = current;
}
return node;
}
struct node *addNode ( const int val )
{
struct node *tmp = malloc ( sizeof ( struct node ) );
if ( tmp == NULL )
{
return NULL;
}
tmp->property = val;
tmp->next = NULL;
return tmp;
}
void freeList ( struct node *head )
{
if ( head == NULL )
{
printf ( "Error, NULL detected in freeList\n" );
return;
}
g_print ( "Valgrind, Bad Results\n" );
///printf ( "No bad results\n" );
struct node *current = head;
while ( current != NULL )
{
struct node *tmp = current->next;
free ( current );
current = tmp;
}
}
Here it is indeed the glib.h
header file included because I call the g_print()
function inside freeList()
function after NULL pointer detection.
Basically, the g_print()
function never gets callled, because I call freeList
in main with NULL
argument, but watch how response valgrid on it:
==10357== Memcheck, a memory error detector
==10357== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==10357== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==10357== Command: ./GSList
==10357==
Error, NULL detected in freeList
==10357==
==10357== HEAP SUMMARY:
==10357== in use at exit: 18,692 bytes in 11 blocks
==10357== total heap usage: 12 allocs, 1 frees, 19,716 bytes allocated
==10357==
==10357== 4 bytes in 1 blocks are still reachable in loss record 1 of 8
==10357== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10357== by 0x4905743: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x4905D63: g_private_get (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48D72A0: g_slice_alloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48A6181: g_hash_table_new_full (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48C9602: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x4011B89: call_init.part.0 (dl-init.c:72)
==10357== by 0x4011C90: call_init (dl-init.c:30)
==10357== by 0x4011C90: _dl_init (dl-init.c:119)
==10357== by 0x4001139: ??? (in /lib/x86_64-linux-gnu/ld-2.31.so)
==10357==
==10357== 32 bytes in 1 blocks are still reachable in loss record 2 of 8
==10357== at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10357== by 0x48BED30: g_malloc0 (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48A4F8F: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48A61C0: g_hash_table_new_full (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48C9602: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x4011B89: call_init.part.0 (dl-init.c:72)
==10357== by 0x4011C90: call_init (dl-init.c:30)
==10357== by 0x4011C90: _dl_init (dl-init.c:119)
==10357== by 0x4001139: ??? (in /lib/x86_64-linux-gnu/ld-2.31.so)
==10357==
==10357== 64 bytes in 1 blocks are still reachable in loss record 3 of 8
==10357== at 0x483B723: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10357== by 0x483E017: realloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10357== by 0x48BED7F: g_realloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48A4F7A: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48A61C0: g_hash_table_new_full (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48C9602: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x4011B89: call_init.part.0 (dl-init.c:72)
==10357== by 0x4011C90: call_init (dl-init.c:30)
==10357== by 0x4011C90: _dl_init (dl-init.c:119)
==10357== by 0x4001139: ??? (in /lib/x86_64-linux-gnu/ld-2.31.so)
==10357==
==10357== 64 bytes in 4 blocks are indirectly lost in loss record 4 of 8
==10357== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10357== by 0x10925A: addNode (main.c:49)
==10357== by 0x10920B: createList (main.c:35)
==10357== by 0x1091C5: main (main.c:21)
==10357==
==10357== 80 (16 direct, 64 indirect) bytes in 1 blocks are definitely lost in loss record 5 of 8
==10357== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10357== by 0x10925A: addNode (main.c:49)
==10357== by 0x10920B: createList (main.c:35)
==10357== by 0x1091C5: main (main.c:21)
==10357==
==10357== 96 bytes in 1 blocks are still reachable in loss record 6 of 8
==10357== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10357== by 0x48BECD8: g_malloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48D72C5: g_slice_alloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48A6181: g_hash_table_new_full (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48C9602: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x4011B89: call_init.part.0 (dl-init.c:72)
==10357== by 0x4011C90: call_init (dl-init.c:30)
==10357== by 0x4011C90: _dl_init (dl-init.c:119)
==10357== by 0x4001139: ??? (in /lib/x86_64-linux-gnu/ld-2.31.so)
==10357==
==10357== 2,032 bytes in 1 blocks are still reachable in loss record 7 of 8
==10357== at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10357== by 0x48BED30: g_malloc0 (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48E29C5: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48D7512: g_slice_alloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48A6181: g_hash_table_new_full (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48C9602: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x4011B89: call_init.part.0 (dl-init.c:72)
==10357== by 0x4011C90: call_init (dl-init.c:30)
==10357== by 0x4011C90: _dl_init (dl-init.c:119)
==10357== by 0x4001139: ??? (in /lib/x86_64-linux-gnu/ld-2.31.so)
==10357==
==10357== 16,384 bytes in 1 blocks are still reachable in loss record 8 of 8
==10357== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10357== by 0x48BECD8: g_malloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x48C9613: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==10357== by 0x4011B89: call_init.part.0 (dl-init.c:72)
==10357== by 0x4011C90: call_init (dl-init.c:30)
==10357== by 0x4011C90: _dl_init (dl-init.c:119)
==10357== by 0x4001139: ??? (in /lib/x86_64-linux-gnu/ld-2.31.so)
==10357==
==10357== LEAK SUMMARY:
==10357== definitely lost: 16 bytes in 1 blocks
==10357== indirectly lost: 64 bytes in 4 blocks
==10357== possibly lost: 0 bytes in 0 blocks
==10357== still reachable: 18,612 bytes in 6 blocks
==10357== suppressed: 0 bytes in 0 blocks
==10357==
==10357== For lists of detected and suppressed errors, rerun with: -s
==10357== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Now if I comment the g_print()
call and call printf()
the things are looking much more differently:
==10384== Memcheck, a memory error detector
==10384== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==10384== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==10384== Command: ./GSList
==10384==
Error, NULL detected in freeList
==10384==
==10384== HEAP SUMMARY:
==10384== in use at exit: 80 bytes in 5 blocks
==10384== total heap usage: 6 allocs, 1 frees, 1,104 bytes allocated
==10384==
==10384== 64 bytes in 4 blocks are indirectly lost in loss record 1 of 2
==10384== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10384== by 0x10923A: addNode (main.c:49)
==10384== by 0x1091EB: createList (main.c:35)
==10384== by 0x1091A5: main (main.c:21)
==10384==
==10384== 80 (16 direct, 64 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==10384== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10384== by 0x10923A: addNode (main.c:49)
==10384== by 0x1091EB: createList (main.c:35)
==10384== by 0x1091A5: main (main.c:21)
==10384==
==10384== LEAK SUMMARY:
==10384== definitely lost: 16 bytes in 1 blocks
==10384== indirectly lost: 64 bytes in 4 blocks
==10384== possibly lost: 0 bytes in 0 blocks
==10384== still reachable: 0 bytes in 0 blocks
==10384== suppressed: 0 bytes in 0 blocks
==10384==
==10384== For lists of detected and suppressed errors, rerun with: -s
==10384== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Now if this case happens in 20-30 functions then you can imagine how many false results has to print valgrind, and the question is WHY?
I am only interested in this particular cases, where g_print should never be called, but valgrind
sees it.
What does g_print()
function different from printf()
in this case?
Valgrind cmd:
valgrind --leak-check=full --track-origins=yes --show-reachable=yes ./program