`g_uuid_string_random` leaves reachable memory behind

Even after g_free() the pointer to g_uuid_create_random() variable, valgrind shows memory reachable.

#include <glib.h>
#include <glib/gi18n.h>

gint main(gint argc, gchar *argv[]) { 

    gchar id[37];
    gchar *rnduuid = g_uuid_string_random();
    g_strlcpy(id, rnduuid, 37);
    g_free(rnduuid);
    g_print("%s\n", id);

    return EXIT_SUCCESS;
}

The valgrind output shows:

$ valgrind -s  --leak-check=full  --show-leak-kinds=all ./uuid_lost 
==115757== Memcheck, a memory error detector
==115757== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==115757== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==115757== Command: ./uuid_lost
==115757== 
6d0aeae3-ad06-4370-9f22-037f11d3c45a
==115757== 
==115757== HEAP SUMMARY:
==115757==     in use at exit: 21,170 bytes in 11 blocks
==115757==   total heap usage: 25 allocs, 14 frees, 56,539 bytes allocated
==115757== 
==115757== 4 bytes in 1 blocks are still reachable in loss record 1 of 11
==115757==    at 0x483677F: malloc (vg_replace_malloc.c:309)
==115757==    by 0x490AD03: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x490B2FB: g_private_get (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48DD1CC: g_slice_alloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48ACC9D: g_hash_table_new_full (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48CF88A: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x400F369: call_init.part.0 (dl-init.c:72)
==115757==    by 0x400F468: call_init (dl-init.c:30)
==115757==    by 0x400F468: _dl_init (dl-init.c:119)
==115757==    by 0x40010C9: ??? (in /usr/lib/x86_64-linux-gnu/ld-2.30.so)
==115757== 
==115757== 4 bytes in 1 blocks are still reachable in loss record 2 of 11
==115757==    at 0x483677F: malloc (vg_replace_malloc.c:309)
==115757==    by 0x490AD03: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x490B2FB: g_private_get (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x4897E18: g_get_charset (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48C8439: g_print (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x1091E6: main (uuid_lost.c:12)
==115757== 
==115757== 15 bytes in 1 blocks are still reachable in loss record 3 of 11
==115757==    at 0x483677F: malloc (vg_replace_malloc.c:309)
==115757==    by 0x48C51C8: g_malloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48DEE3F: g_strdup (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x4897E98: g_get_charset (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48C8439: g_print (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x1091E6: main (uuid_lost.c:12)
==115757== 
==115757== 15 bytes in 1 blocks are still reachable in loss record 4 of 11
==115757==    at 0x483677F: malloc (vg_replace_malloc.c:309)
==115757==    by 0x48C51C8: g_malloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48DEE3F: g_strdup (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x4897F05: g_get_charset (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48C8439: g_print (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x1091E6: main (uuid_lost.c:12)
==115757== 
==115757== 24 bytes in 1 blocks are still reachable in loss record 5 of 11
==115757==    at 0x4838B65: calloc (vg_replace_malloc.c:762)
==115757==    by 0x48C5220: g_malloc0 (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48E85A1: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x4897F30: g_get_charset (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48C8439: g_print (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x1091E6: main (uuid_lost.c:12)
==115757== 
==115757== 32 bytes in 1 blocks are still reachable in loss record 6 of 11
==115757==    at 0x4838B65: calloc (vg_replace_malloc.c:762)
==115757==    by 0x48C5220: g_malloc0 (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48ABAAF: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48ACCDC: g_hash_table_new_full (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48CF88A: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x400F369: call_init.part.0 (dl-init.c:72)
==115757==    by 0x400F468: call_init (dl-init.c:30)
==115757==    by 0x400F468: _dl_init (dl-init.c:119)
==115757==    by 0x40010C9: ??? (in /usr/lib/x86_64-linux-gnu/ld-2.30.so)
==115757== 
==115757== 64 bytes in 1 blocks are still reachable in loss record 7 of 11
==115757==    at 0x48366AF: malloc (vg_replace_malloc.c:308)
==115757==    by 0x4838DE7: realloc (vg_replace_malloc.c:836)
==115757==    by 0x48C5267: g_realloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48ABA9A: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48ACCDC: g_hash_table_new_full (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48CF88A: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x400F369: call_init.part.0 (dl-init.c:72)
==115757==    by 0x400F468: call_init (dl-init.c:30)
==115757==    by 0x400F468: _dl_init (dl-init.c:119)
==115757==    by 0x40010C9: ??? (in /usr/lib/x86_64-linux-gnu/ld-2.30.so)
==115757== 
==115757== 96 bytes in 1 blocks are still reachable in loss record 8 of 11
==115757==    at 0x483677F: malloc (vg_replace_malloc.c:309)
==115757==    by 0x48C51C8: g_malloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48DD1F1: g_slice_alloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48ACC9D: g_hash_table_new_full (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48CF88A: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x400F369: call_init.part.0 (dl-init.c:72)
==115757==    by 0x400F468: call_init (dl-init.c:30)
==115757==    by 0x400F468: _dl_init (dl-init.c:119)
==115757==    by 0x40010C9: ??? (in /usr/lib/x86_64-linux-gnu/ld-2.30.so)
==115757== 
==115757== 2,032 bytes in 1 blocks are still reachable in loss record 9 of 11
==115757==    at 0x4838B65: calloc (vg_replace_malloc.c:762)
==115757==    by 0x48C5220: g_malloc0 (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48E85A1: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48DD442: g_slice_alloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48ACC9D: g_hash_table_new_full (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48CF88A: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x400F369: call_init.part.0 (dl-init.c:72)
==115757==    by 0x400F468: call_init (dl-init.c:30)
==115757==    by 0x400F468: _dl_init (dl-init.c:119)
==115757==    by 0x40010C9: ??? (in /usr/lib/x86_64-linux-gnu/ld-2.30.so)
==115757== 
==115757== 2,500 bytes in 1 blocks are still reachable in loss record 10 of 11
==115757==    at 0x4838B65: calloc (vg_replace_malloc.c:762)
==115757==    by 0x48C5220: g_malloc0 (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48D1324: g_rand_new_with_seed_array (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48D13F1: g_rand_new (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48D181C: g_random_int (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48F6D18: g_uuid_string_random (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x1091A6: main (uuid_lost.c:9)
==115757== 
==115757== 16,384 bytes in 1 blocks are still reachable in loss record 11 of 11
==115757==    at 0x483677F: malloc (vg_replace_malloc.c:309)
==115757==    by 0x48C51C8: g_malloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x48CF89B: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.3)
==115757==    by 0x400F369: call_init.part.0 (dl-init.c:72)
==115757==    by 0x400F468: call_init (dl-init.c:30)
==115757==    by 0x400F468: _dl_init (dl-init.c:119)
==115757==    by 0x40010C9: ??? (in /usr/lib/x86_64-linux-gnu/ld-2.30.so)
==115757== 
==115757== LEAK SUMMARY:
==115757==    definitely lost: 0 bytes in 0 blocks
==115757==    indirectly lost: 0 bytes in 0 blocks
==115757==      possibly lost: 0 bytes in 0 blocks
==115757==    still reachable: 21,170 bytes in 11 blocks
==115757==         suppressed: 0 bytes in 0 blocks
==115757== 
==115757== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Is safe to ignore this? Is it a bug? Am I doing something wrong?

There are a number of deliberate once-per-process leaks in GLib, and some false positives. GLib has a Valgrind suppressions file which is supposed to cover these. Have you tried running your test program with that?

Also, with valgrind, try to use G_SLICE=always-malloc

That’s not necessary, unless you’re using a very old version of GLib.

Newer versions of GLib can detect when they are running under Valgrind, and automatically disable the slice allocator.

3 Likes

Yes. I’m running with it. Checking the valgrind output against the provided suppression file, seems (just for sake of example), that the first case isn’t covered.

There is no suppression entry that covers:

fun:malloc
...
fun:g_private_get

or

fun:malloc
...
fun:g_slice_alloc

or (what seems more correct)

fun:malloc
...
fun:g_hash_table_new_full

I could not see where in this code g_hash_table_new_full() is being called.

Since I’m just a newbie, I will leave to the experts to decide if it is a bug or a expected false-positive that should be added to glib’s valgrind suppression file.

Also note that g_print(), also leaves a reachable region.

If you think there is a bug in GLib, report it to gitlab.gnome.org/gnome/glib !

1 Like

Done https://gitlab.gnome.org/GNOME/glib/-/issues/2134

The g_hash_table* comes from the library initializer; the suppression file would catch them, but you seem to be missing the debug symbols for glib so valgrind has issues matching that.

2 Likes

Seems there is no package in debian for glib debug symbols.

$ apt-cache search libglib
libglibd-2.0-0 - GLib library of C routines - D bindings
libglibd-2.0-dev - GLib library of C routines - development files for D
libglib2.0-0 - GLib library of C routines
libglib2.0-bin - Programs for the GLib library
libglib2.0-data - Common files for GLib library
libglib2.0-dev - Development files for the GLib library
libglib2.0-dev-bin - Development utilities for the GLib library
libglib2.0-doc - Documentation files for the GLib library
libglib2.0-tests - GLib library of C routines - installed tests
libglibmm-2.4-1v5 - C++ wrapper for the GLib toolkit (shared libraries)
libglibmm-2.4-dev - C++ wrapper for the GLib toolkit (development files)
libglibmm-2.4-doc - C++ wrapper for the GLib toolkit (documentation)
libglib2.0-cil - CLI binding for the GLib utility library 2.12
libglib2.0-cil-dev - CLI binding for the GLib utility library 2.12
libglib3.0-cil - CLI binding for the GLib library of C routines
libglib3.0-cil-dev - CLI binding for the GLib utility library 2.12
gvfs-bin - userspace virtual filesystem - deprecated command-line tools
libglib-object-introspection-perl - Perl bindings for gobject-introspection libraries
libglib-perl - interface to the GLib and GObject libraries
libglib-testing-0-0 - test library providing test harnesses and mock classes
libglib-testing-0-dev - Development files for the libglib-testing library
libglib-testing-doc - Documentation for the libglib-testing library
librust-glib-sys-dev - FFI bindings to libglib-2.0 - Rust source code

so bad. =/

Since $recently, you have to enable the debug symbol repository, see https://wiki.debian.org/HowToGetABacktrace#Installing_the_debugging_symbols

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.