g_type_register_fundamental() and g_type_add_interface_static() should not trigger valgrind leak warnings
The GType machinery in gtype.c intentionally leaks memory for type registrations. The memory is allocated exactly once and used until the end of the program, so it's not necessarily a bug, per se. But it makes it harder to debug real memory leaks, so I propose we modify the code to avoid triggering these warnings. GLib has a glib.supp valgrind suppressions file to ignore these, but it has to be used manually, which is cumbersome, so not many people ever bother with it (I don't). So it would be nice to avoid these issues by default.
As far as I can tell, there are only two places in GType where we have actual problematic allocations, and these two points make up the vast majority of valgrind leak warnings caused by GLib:
==180238== 16 bytes in 1 blocks are possibly lost in loss record 3,078 of 16,075
==180238== at 0x483BB1A: calloc (vg_replace_malloc.c:762)
==180238== by 0x5489495: g_malloc0 (gmem.c:132)
==180238== by 0x5489754: g_malloc0_n (gmem.c:364)
==180238== by 0x53FDBEE: type_set_qdata_W (gtype.c:3722)
==180238== by 0x53FDEE8: type_add_flags_W (gtype.c:3787)
==180238== by 0x53FC348: g_type_register_fundamental (gtype.c:2662)
==180238== by 0x53D969B: _g_enum_types_init (genums.c:124)
==180238== by 0x53FF058: gobject_init (gtype.c:4432)
==180238== by 0x53FF082: gobject_init_ctor (gtype.c:4493)
==180238== by 0x4010F29: call_init.part.0 (dl-init.c:72)
==180238== by 0x4011030: call_init (dl-init.c:30)
==180238== by 0x4011030: _dl_init (dl-init.c:119)
==180238== by 0x4002149: ??? (in /usr/lib64/ld-2.30.so)
This one is caused because instead of storing a pointer to the start of the type node, GType instead stores an "internal pointer" past the beginning of the allocated memory region. Normally, as long as a pointer to the start of the memory region exists when the program exits, valgrind will not complain about it. But because GLib is storing a pointer to an area past the beginning of the memory region, valgrind thinks the memory is unreachable and detects it as possibly lost. Workaround to avoid these warnings looks like this:
diff --git a/gobject/gtype.c b/gobject/gtype.c
index b5ef2d11e..9a0490c72 100644
--- a/gobject/gtype.c
+++ b/gobject/gtype.c
@@ -430,6 +430,22 @@ type_node_any_new_W (TypeNode *pnode,
TypeNode *node;
guint i, node_size = 0;
+#if ENABLE_VALGRIND
+ /* Ensure one-time "leaked" nodes remain reachable by valgrind. This
+ * in necessary because we don't otherwise store pointers directly to
+ * the start of the allocated memory, only interior pointers.
+ *
+ * Note that the use of G_TYPE_FUNDAMENTAL_MAX here is slightly
+ * arbitrary. We need to use a value significantly larger than
+ * G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT, because that
+ * is the maximum number of *unparented nodes*, but here we have to
+ * hold *all* nodes. Realistically, this will certainly be large
+ * enough, but we'll assert this at runtime to be certain.
+ */
+ static TypeNode *still_reachable_nodes[G_TYPE_FUNDAMENTAL_MAX] = { 0, };
+ static guint n_nodes = 0;
+#endif
+
n_supers = pnode ? pnode->n_supers + 1 : 0;
if (!pnode)
@@ -437,6 +453,17 @@ type_node_any_new_W (TypeNode *pnode,
node_size += SIZEOF_BASE_TYPE_NODE (); /* TypeNode structure */
node_size += (sizeof (GType) * (1 + n_supers + 1)); /* self + ancestors + (0) for ->supers[] */
node = g_malloc0 (node_size);
+
+#if ENABLE_VALGRIND
+ if (RUNNING_ON_VALGRIND)
+ {
+ (void)still_reachable_nodes[0]; /* Suppress -Wunused-variable. */
+ if (n_nodes == G_TYPE_FUNDAMENTAL_MAX)
+ g_assert_not_reached ();
+ still_reachable_nodes[n_nodes++] = node;
+ }
+#endif
+
if (!pnode) /* offset fundamental types */
{
node = G_STRUCT_MEMBER_P (node, SIZEOF_FUNDAMENTAL_INFO);
That's not too much extra code, and I think it's a small price to pay to make valgrinding significantly easier. That solves half the problems. If you're OK with this workaround, I'll propose an MR.
The other half of the problems look like this:
==180238== 16 bytes in 1 blocks are possibly lost in loss record 3,086 of 16,075
==180238== at 0x483980B: malloc (vg_replace_malloc.c:309)
==180238== by 0x548942C: g_malloc (gmem.c:102)
==180238== by 0x54A4748: g_slice_alloc (gslice.c:1025)
==180238== by 0x53D0AAF: freelist_alloc (gatomicarray.c:77)
==180238== by 0x53D0B85: _g_atomic_array_copy (gatomicarray.c:133)
==180238== by 0x53F8E6D: iface_node_set_offset_L (gtype.c:1347)
==180238== by 0x53F91F1: type_node_add_iface_entry_W (gtype.c:1444)
==180238== by 0x53F93DF: type_add_interface_Wm (gtype.c:1477)
==180238== by 0x53FC946: g_type_add_interface_static (gtype.c:2852)
==180238== by 0x4A3D53A: gtk_menu_shell_accessible_get_type_once (gtkmenushellaccessible.c:26)
==180238== by 0x4A3D495: gtk_menu_shell_accessible_get_type (gtkmenushellaccessible.c:26)
==180238== by 0x4C8AC44: gtk_menu_shell_class_init (gtkmenushell.c:424)
This is a different case and, despite some effort, I'm uncertain what the problem is here and haven't figured out how to avoid it. I can create a separate bug report for this if you want.