Valgring is reporting about non-freed heap memory even after a call to g_array_free()
.
I have ran valgrind
using --suppressions=/usr/share/glib-2.0/valgrind/glib.supp
, but the errors persist, hence I think that I’m doing something wrong while freeing memory.
Please, how can I fix ?
#include <stdlib.h>
#include <glib.h>
struct dataframe
{
gfloat fNumber;
gint dNumber;
GArray *vector;
};
struct vector
{
gfloat x;
gfloat y;
};
struct dataframe *
dataframe_init() {
struct dataframe *df = malloc(sizeof *df);
df->fNumber = 3.1415;
df->dNumber = 42;
df->vector = g_array_new(FALSE, FALSE, sizeof(df->vector));
return df;
}
void
dataframe_free(struct dataframe *df) {
if(df)
if(df->vector)
g_array_free(df->vector, TRUE);
free(df);
}
void
dataframe_print(struct dataframe *df) {
struct vector v;
g_print("The float: %6.4f\n", df->fNumber);
g_print("The int: %06d\n", df->dNumber);
g_print("Vector count %d\n", df->vector->len);
for(size_t i = 0; i < df->vector->len; i++) {
v = g_array_index(df->vector, struct vector, i);
g_print("v_%02d: (%6.2f, %6.2f)\n", i, v.x, v.y);
}
}
gint main(gint argc, gchar *argv[]) {
struct dataframe * df = dataframe_init();
struct vector v;
v = (struct vector){ 1.2f, 3.2f };
g_array_append_val(df->vector, v);
v = (struct vector){ 0.4f, 4.2f };
g_array_append_val(df->vector, v);
v = (struct vector){ 2.4f, 0.2f };
g_array_append_val(df->vector, v);
dataframe_print(df);
dataframe_free(df);
return 0;
}
I compile the code above with:
gcc -Wall --pedantic -ggdb gfree_test.c -o gfree_test $(pkg-config --cflags --libs glib-2.0)
Checked with Clang’s static analyzer
$ scan-build-11 -v gcc --std=c2x -Wall --pedantic -ggdb gfree_test.c -o gfree_test $(pkg-config --cflags --libs glib-2.0)
scan-build: Using '/usr/lib/llvm-11/bin/clang' for static analysis
scan-build: Emitting reports for this run to '/tmp/scan-build-2020-05-20-034333-30214-1'.
scan-build: Analysis run complete.
scan-build: Removing directory '/tmp/scan-build-2020-05-20-034333-30214-1' because it contains no reports.
scan-build: No bugs found.
And run with
$ valgrind --suppressions=/usr/share/glib-2.0/valgrind/glib.supp ./gfree_test
==28121== Memcheck, a memory error detector
==28121== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==28121== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==28121== Command: ./gfree_test
==28121==
The float: 3.1415
The int: 000042
Vector count 3
v_00: ( 1.20, 3.20)
v_01: ( 0.40, 4.20)
v_02: ( 2.40, 0.20)
==28121==
==28121== HEAP SUMMARY:
==28121== in use at exit: 18,670 bytes in 10 blocks
==28121== total heap usage: 53 allocs, 43 frees, 218,956 bytes allocated
==28121==
==28121== LEAK SUMMARY:
==28121== definitely lost: 0 bytes in 0 blocks
==28121== indirectly lost: 0 bytes in 0 blocks
==28121== possibly lost: 0 bytes in 0 blocks
==28121== still reachable: 18,670 bytes in 10 blocks
==28121== suppressed: 0 bytes in 0 blocks
==28121== Rerun with --leak-check=full to see details of leaked memory
==28121==
==28121== For lists of detected and suppressed errors, rerun with: -s
==28121== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
For sake of completeness, the leaks shown by valgrind
are:
==30135== 4 bytes in 1 blocks are still reachable in loss record 1 of 10
==30135== at 0x483677F: malloc (vg_replace_malloc.c:309)
==30135== by 0x4908D03: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x49092FB: g_private_get (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48DB1CC: g_slice_alloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48AAC9D: g_hash_table_new_full (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48CD88A: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x400F369: call_init.part.0 (dl-init.c:72)
==30135== by 0x400F468: call_init (dl-init.c:30)
==30135== by 0x400F468: _dl_init (dl-init.c:119)
==30135== by 0x40010C9: ??? (in /usr/lib/x86_64-linux-gnu/ld-2.30.so)
==30135==
==30135== 4 bytes in 1 blocks are still reachable in loss record 2 of 10
==30135== at 0x483677F: malloc (vg_replace_malloc.c:309)
==30135== by 0x4908D03: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x49092FB: g_private_get (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x4895E18: g_get_charset (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48C6439: g_print (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x109244: dataframe_print (gfree_test.c:43)
==30135== by 0x1093B4: main (gfree_test.c:69)
==30135==
==30135== 15 bytes in 1 blocks are still reachable in loss record 3 of 10
==30135== at 0x483677F: malloc (vg_replace_malloc.c:309)
==30135== by 0x48C31C8: g_malloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48DCE3F: g_strdup (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x4895E98: g_get_charset (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48C6439: g_print (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x109244: dataframe_print (gfree_test.c:43)
==30135== by 0x1093B4: main (gfree_test.c:69)
==30135==
==30135== 15 bytes in 1 blocks are still reachable in loss record 4 of 10
==30135== at 0x483677F: malloc (vg_replace_malloc.c:309)
==30135== by 0x48C31C8: g_malloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48DCE3F: g_strdup (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x4895F05: g_get_charset (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48C6439: g_print (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x109244: dataframe_print (gfree_test.c:43)
==30135== by 0x1093B4: main (gfree_test.c:69)
==30135==
==30135== 24 bytes in 1 blocks are still reachable in loss record 5 of 10
==30135== at 0x4838B65: calloc (vg_replace_malloc.c:762)
==30135== by 0x48C3220: g_malloc0 (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48E65A1: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x4895F30: g_get_charset (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48C6439: g_print (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x109244: dataframe_print (gfree_test.c:43)
==30135== by 0x1093B4: main (gfree_test.c:69)
==30135==
==30135== 32 bytes in 1 blocks are still reachable in loss record 6 of 10
==30135== at 0x4838B65: calloc (vg_replace_malloc.c:762)
==30135== by 0x48C3220: g_malloc0 (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48A9AAF: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48AACDC: g_hash_table_new_full (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48CD88A: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x400F369: call_init.part.0 (dl-init.c:72)
==30135== by 0x400F468: call_init (dl-init.c:30)
==30135== by 0x400F468: _dl_init (dl-init.c:119)
==30135== by 0x40010C9: ??? (in /usr/lib/x86_64-linux-gnu/ld-2.30.so)
==30135==
==30135== 64 bytes in 1 blocks are still reachable in loss record 7 of 10
==30135== at 0x48366AF: malloc (vg_replace_malloc.c:308)
==30135== by 0x4838DE7: realloc (vg_replace_malloc.c:836)
==30135== by 0x48C3267: g_realloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48A9A9A: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48AACDC: g_hash_table_new_full (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48CD88A: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x400F369: call_init.part.0 (dl-init.c:72)
==30135== by 0x400F468: call_init (dl-init.c:30)
==30135== by 0x400F468: _dl_init (dl-init.c:119)
==30135== by 0x40010C9: ??? (in /usr/lib/x86_64-linux-gnu/ld-2.30.so)
==30135==
==30135== 96 bytes in 1 blocks are still reachable in loss record 8 of 10
==30135== at 0x483677F: malloc (vg_replace_malloc.c:309)
==30135== by 0x48C31C8: g_malloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48DB1F1: g_slice_alloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48AAC9D: g_hash_table_new_full (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48CD88A: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x400F369: call_init.part.0 (dl-init.c:72)
==30135== by 0x400F468: call_init (dl-init.c:30)
==30135== by 0x400F468: _dl_init (dl-init.c:119)
==30135== by 0x40010C9: ??? (in /usr/lib/x86_64-linux-gnu/ld-2.30.so)
==30135==
==30135== 2,032 bytes in 1 blocks are still reachable in loss record 9 of 10
==30135== at 0x4838B65: calloc (vg_replace_malloc.c:762)
==30135== by 0x48C3220: g_malloc0 (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48E65A1: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48DB442: g_slice_alloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48AAC9D: g_hash_table_new_full (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48CD88A: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x400F369: call_init.part.0 (dl-init.c:72)
==30135== by 0x400F468: call_init (dl-init.c:30)
==30135== by 0x400F468: _dl_init (dl-init.c:119)
==30135== by 0x40010C9: ??? (in /usr/lib/x86_64-linux-gnu/ld-2.30.so)
==30135==
==30135== 16,384 bytes in 1 blocks are still reachable in loss record 10 of 10
==30135== at 0x483677F: malloc (vg_replace_malloc.c:309)
==30135== by 0x48C31C8: g_malloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x48CD89B: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.2)
==30135== by 0x400F369: call_init.part.0 (dl-init.c:72)
==30135== by 0x400F468: call_init (dl-init.c:30)
==30135== by 0x400F468: _dl_init (dl-init.c:119)
==30135== by 0x40010C9: ??? (in /usr/lib/x86_64-linux-gnu/ld-2.30.so)
==30135==