I'm using GDBus (via Glib) and I have code like:
method_call_message = g_dbus_message_new_method_call(owner,
OBJECT_PATH,
INTERFACE_NAME,
"get_snmpv2_mib");
GVariant *gv = g_variant_new("(sissi)", ip, port, mib, variable, instance);
g_dbus_message_set_body(method_call_message, gv);
I assume method_call_message is now a container for gv.
Before exiting I call:
g_object_unref(method_call_message);
I assume this will then schedule BOTH method_call_message and gv for GC?
When is GC done?
I appear to be leaking some 4 bytes at a time as I watch the top updates on VIRT memory.
I have commented out pieces of code till I localized it (the leak) to my GDBus calls.
Using some Valgrind magic:
libtool exec valgrind --tool=memcheck --leak-check=full --log-file=w <executable + args>
I was able to winnow out the memory management obfuscation and get to a call-stack that showed the problem. The Valgrind output indicated that all my memory losses were associated with calls to g_variant_get(...):
at 0x4A06A2E: malloc (vg_replace_malloc.c:270)
==20088== by 0x3F21E503B6: g_malloc (in /usr/lib64/libglib-2.0.so.0.4400.1)
==20088== by 0x3F21E6860D: g_strdup (in /usr/lib64/libglib-2.0.so.0.4400.1)
==20088== by 0x3F21E7FD01: ??? (in /usr/lib64/libglib-2.0.so.0.4400.1)
==20088== by 0x3F21E7FA61: ??? (in /usr/lib64/libglib-2.0.so.0.4400.1)
==20088== by 0x3F21E80348: g_variant_get_va (in /usr/lib64/libglib-2.0.so.0.4400.1)
==20088== by 0x3F21E80585: g_variant_get (in /usr/lib64/libglib-2.0.so.0.4400.1)
==20088== by 0x4C30555: server_gvariant (in /usr/lib64/libdrsnvc.so)
==20088== by 0x40257B: NVCtimerCB(void*) (main.cc:73)
==20088== by 0x3F21E48C3A: ??? (in /usr/lib64/libglib-2.0.so.0.4400.1)
==20088== by 0x3F21E48519: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.4400.1)
==20088== by 0x3F21E4A5A7: ??? (in /usr/lib64/libglib-2.0.so.0.4400.1)
Obviously the call to g_variant_get(...) begats a call to g_strdup(...) (if your format_string includes an 's' for string). So, in my case, the code is:
g_variant_get(response, "(isi)", &od.stat, &od.msg, &od.i);
gchar *tmp = od.msg;
od.msg = strncpy(msg, od.msg, strlen(od.msg)); /* copy string */
g_free(tmp); /* free g_strdup allocated space */
And a call to g_free(...) frees the allocated storage.
Now I get:
LEAK SUMMARY:
==6472== definitely lost: 0 bytes in 0 blocks
==6472== indirectly lost: 0 bytes in 0 blocks
==6472== possibly lost: 9,841 bytes in 148 blocks
==6472== still reachable: 106,376 bytes in 986 blocks
==6472== suppressed: 0 bytes in 0 blocks