Valgrind reports memory leak with gtk4

I compiled the Helloworld from here Gtk – 4.0: Getting Started with GTK

When I run this with valgrind --leak-check=full ./main it has a lot of memory leaks. It fills up several pages in the terminal.
Is this normal?

GTK, and various other libraries used by GTK, perform one-off allocations that Valgrind register as a “leak”.

You will need to use suppression files provided by GLib and GTK to reduce the amount of false positives.

You probably want to read the introduction to Valgrind on the GNOME developers documentation website.

1 Like

I’ve tried this now, but it didn’t help much.

What also surprises me is that I’ve tried the whole thing with pure glib2.

If I do it like this valgrind --leak-check=full --trace-children=yes ./main everything is fine, unless I make a leak in my own code.

But if I call the following, I see leaks in glib2 too.
valgrind --leak-check=full --trace-children=yes ./main

Why does GTK4 behave differently than glib2?

Because GTK4 has a lot more things to initialise, more objects to create, and has more dependencies that may do one-off allocations.

For instance, GTK4 initialises Vulkan or OpenGL, and the driver can initialise their own shader cache, for instance:

==2039413== 213,920 bytes in 2,674 blocks are possibly lost in loss record 11,049 of 11,050
==2039413==    at 0x4845866: malloc (vg_replace_malloc.c:446)
==2039413==    by 0x2642B06C: ralloc_size (ralloc.c:118)
==2039413==    by 0x2644505B: mesa_db_update_index (mesa_cache_db.c:272)
==2039413==    by 0x2644524A: mesa_db_load (mesa_cache_db.c:341)
==2039413==    by 0x26445A06: mesa_cache_db_open (mesa_cache_db.c:623)
==2039413==    by 0x264322D0: mesa_cache_db_multipart_open (mesa_cache_db_multipart.c:42)
==2039413==    by 0x26422CFA: disk_cache_type_create (disk_cache.c:145)
==2039413==    by 0x26422E6C: disk_cache_create (disk_cache.c:286)
==2039413==    by 0x262F1D46: radv_physical_device_try_create (radv_physical_device.c:2180)
==2039413==    by 0x263A5BDF: enumerate_drm_physical_devices_locked (vk_instance.c:411)
==2039413==    by 0x263A5D01: enumerate_physical_devices_locked (vk_instance.c:442)
==2039413==    by 0x263A5D01: enumerate_physical_devices (vk_instance.c:459)
==2039413==    by 0x263A6871: vk_common_EnumeratePhysicalDevices (vk_instance.c:475)
==2039413==    by 0x55DD9BA: setup_loader_term_phys_devs (loader.c:6300)
==2039413==    by 0x55DE1CC: terminator_EnumeratePhysicalDevices (loader.c:6634)
==2039413==    by 0x26DF9B22: device_select_EnumeratePhysicalDevices (device_select_layer.c:553)
==2039413==    by 0x55E89D2: vkEnumeratePhysicalDevices (trampoline.c:902)
==2039413==    by 0x4C5AD40: gdk_display_create_vulkan_device (gdkvulkancontext.c:1461)
==2039413==    by 0x4C5BD02: gdk_display_create_vulkan_instance (gdkvulkancontext.c:1781)
==2039413==    by 0x4C5DDC4: gdk_display_init_vulkan (gdkvulkancontext.c:1827)
==2039413==    by 0x4C6D858: vulkan_supported_platform (gskrenderer.c:656)

Or the driver could be initialising its own one-off state:

==2039413== 256 bytes in 1 blocks are possibly lost in loss record 10,379 of 11,050
==2039413==    at 0x4845866: malloc (vg_replace_malloc.c:446)
==2039413==    by 0x2642B06C: ralloc_size (ralloc.c:118)
==2039413==    by 0x2642B241: rzalloc_size (ralloc.c:152)
==2039413==    by 0x2642B241: rzalloc_array_size (ralloc.c:232)
==2039413==    by 0x2642C251: set_rehash (set.c:345)
==2039413==    by 0x2642C57D: set_search_or_add (set.c:400)
==2039413==    by 0x2639C1F0: vk_pipeline_cache_insert_object.part.0 (vk_pipeline_cache.c:294)
==2039413==    by 0x2639C642: vk_pipeline_cache_insert_object (vk_pipeline_cache.c:287)
==2039413==    by 0x2639C642: vk_pipeline_cache_add_object (vk_pipeline_cache.c:421)
==2039413==    by 0x262F815E: radv_pipeline_cache_insert (radv_pipeline_cache.c:383)
==2039413==    by 0x262F9061: radv_compute_pipeline_compile (radv_pipeline_compute.c:221)
==2039413==    by 0x262F91B3: radv_compute_pipeline_create (radv_pipeline_compute.c:268)
==2039413==    by 0x26238B1F: radv_meta_create_compute_pipeline (radv_meta.c:743)
==2039413==    by 0x262422B9: create_fill_pipeline (radv_meta_buffer.c:55)
==2039413==    by 0x262422B9: create_fill_pipeline (radv_meta_buffer.c:40)
==2039413==    by 0x26242427: get_fill_pipeline (radv_meta_buffer.c:70)
==2039413==    by 0x26242427: fill_buffer_shader (radv_meta_buffer.c:192)
==2039413==    by 0x26242610: radv_fill_buffer (radv_meta_buffer.c:287)
==2039413==    by 0x2624FEFF: radv_clear_dcc (radv_meta_clear.c:1200)
==2039413==    by 0x262BA0B8: radv_init_dcc (radv_cmd_buffer.c:12473)
==2039413==    by 0x262BA5E1: radv_init_color_image_metadata (radv_cmd_buffer.c:12537)
==2039413==    by 0x262BA5E1: radv_handle_color_image_transition (radv_cmd_buffer.c:12585)
==2039413==    by 0x262BA5E1: radv_handle_image_transition (radv_cmd_buffer.c:12685)
==2039413==    by 0x262BB21A: radv_handle_image_transition_separate (radv_cmd_buffer.c:7235)
==2039413==    by 0x262BB21A: radv_handle_rendering_image_transition (radv_cmd_buffer.c:7266)
==2039413==    by 0x262BB484: radv_CmdBeginRendering (radv_cmd_buffer.c:9416)
==2039413==    by 0x263894EE: begin_subpass.isra.0 (vk_render_pass.c:2189)

It mainly depends on which driver you’re using; I am using the AMD driver inside Mesa, but the Valgrind output might very well be different with Intel or NVidia.

That does not mean that GTK is leak free: that would be like saying that GTK is bug free. Valgrind is also not infallible: since it emulates x86 memory management calls, it can get confused by code that is perfectly valid but happens to exploit details that are not easily described by a simple alloc/free pair.

Reading the Valgrind log is more of an art than a science.

1 Like

In that case, it is not so easy to use valgrind to check whether you are causing a leek in your own code with gtk4?

It seems to work with simple glib2 code.

You have to stop comparing GLib to GTK: the size and scope of these two libraries is not even remotely comparable—unless you’re planning to rewrite the entirety of GTK without using any dependency and without using hardware acceleration.

It’s not “easy” to use a complex tool like Valgrind to begin with. On top of that, Valgrind knows nothing about the GObject reference counting mechanism, so anything causing reference leaks is not going to be detected anyway. At most, Valgrind will should you places where you should investigate.

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