These logs were done with --show-reachable=yes because Valgrind does not always see the memory as lost. The results are quite conclusive:
From gvca:
==12744== 122,531,944 bytes in 373,573 blocks are still reachable in loss record 6,971 of 6,971
==12744== at 0x4024C1C: malloc (vg_replace_malloc.c:195)
==12744== by 0x45972E3: g_malloc (gmem.c:131)
==12744== by 0x45AD418: g_slice_alloc (gslice.c:824)
==12744== by 0x45AD714: g_slice_alloc0 (gslice.c:833)
==12744== by 0x44FD8F6: g_type_create_instance (gtype.c:1654)
==12744== by 0x44E2747: g_object_constructor (gobject.c:1383)
==12744== by 0x44E3707: g_object_newv (gobject.c:1171)
==12744== by 0x44E4589: g_object_new_valist (gobject.c:1323)
==12744== by 0x44E470D: g_object_new (gobject.c:1086)
==12744== by 0x80515FE: gvc_channel_map_new_from_pa_channel_map (gvc-channel-map.c:287)
==12744== by 0x8057552: _pa_context_get_sink_input_info_cb (gvc-mixer-control.c:886)
==12744== by 0x452DB6C: context_get_sink_input_info_callback (introspect.c:1028)
==12744== by 0x4C6CEA4: run_action (pdispatch.c:274)
==12744== by 0x4C6D475: pa_pdispatch_run (pdispatch.c:326)
==12744== by 0x4525148: pstream_packet_callback (context.c:357)
==12744== by 0x4C726E7: do_something (pstream.c:816)
==12744== by 0x4C5D11D: callback (iochannel.c:119)
==12744== by 0x4511F32: ??? (in /usr/lib/libpulse-mainloop-glib.so.0.0.4)
==12744== by 0x458EE87: g_main_context_dispatch (gmain.c:1960)
==12744== by 0x459272F: g_main_context_iterate (gmain.c:2591)
==12744== by 0x4592B9E: g_main_loop_run (gmain.c:2799)
==12744== by 0x418D418: gtk_main (gtkmain.c:1218)
==12744== by 0x804EEF0: main (applet-main.c:92)
==12744==
==12744== LEAK SUMMARY:
==12744== definitely lost: 14,792 bytes in 23 blocks
==12744== indirectly lost: 19,683 bytes in 540 blocks
==12744== possibly lost: 46,340 bytes in 1,836 blocks
==12744== still reachable: 157,160,155 bytes in 1,524,594 blocks
==12744== suppressed: 11,664 bytes in 266 blocks
And in gsd:
==12804== 122,420,096 bytes in 373,232 blocks are possibly lost in loss record 5,433 of 5,433
==12804== at 0x4024C1C: malloc (vg_replace_malloc.c:195)
==12804== by 0x48702E3: g_malloc (gmem.c:131)
==12804== by 0x4886418: g_slice_alloc (gslice.c:824)
==12804== by 0x4886714: g_slice_alloc0 (gslice.c:833)
==12804== by 0x481C8F6: g_type_create_instance (gtype.c:1654)
==12804== by 0x4801747: g_object_constructor (gobject.c:1383)
==12804== by 0x4802707: g_object_newv (gobject.c:1171)
==12804== by 0x4803589: g_object_new_valist (gobject.c:1323)
==12804== by 0x480370D: g_object_new (gobject.c:1086)
==12804== by 0x651BA2E: gvc_channel_map_new_from_pa_channel_map (gvc-channel-map.c:287)
==12804== by 0x6521382: _pa_context_get_sink_input_info_cb (gvc-mixer-control.c:886)
==12804== by 0x5CF2B6C: context_get_sink_input_info_callback (introspect.c:1028)
==12804== by 0x5D41EA4: run_action (pdispatch.c:274)
==12804== by 0x5D42475: pa_pdispatch_run (pdispatch.c:326)
==12804== by 0x5CEA148: pstream_packet_callback (context.c:357)
==12804== by 0x5D476E7: do_something (pstream.c:816)
==12804== by 0x5D3211D: callback (iochannel.c:119)
==12804== by 0x5CD7F32: ??? (in /usr/lib/libpulse-mainloop-glib.so.0.0.4)
==12804== by 0x4867E87: g_main_context_dispatch (gmain.c:1960)
==12804== by 0x486B72F: g_main_context_iterate (gmain.c:2591)
==12804== by 0x486BB9E: g_main_loop_run (gmain.c:2799)
==12804== by 0x417A418: gtk_main (gtkmain.c:1218)
==12804== by 0x804B9AD: main (main.c:489)
==12804==
==12804== LEAK SUMMARY:
==12804== definitely lost: 7,376 bytes in 584 blocks
==12804== indirectly lost: 28,244 bytes in 2,353 blocks
==12804== possibly lost: 149,360,130 bytes in 1,495,604 blocks
==12804== still reachable: 7,059,820 bytes in 13,284 blocks
==12804== suppressed: 9,360 bytes in 221 blocks
gvc_channel_map_new_from_pa_channel_map allocates a channel map every time an applications creates a pulseaudio sink. The map ends up stored in a hash table (in update_sink_input in gvc-mixer-control.c). When the application closes the sink, the channel map is not freed. Eventually the hash table grows very large. This is made far worse by misbehaving apps which open and close the sink repeatedly, such as in my video. Valgrind does not see the memory as lost because it is still reachable through the hash table.
These logs were done with --show- reachable= yes because Valgrind does not always see the memory as lost. The results are quite conclusive:
From gvca: malloc. c:195) create_ instance (gtype.c:1654) constructor (gobject.c:1383) map_new_ from_pa_ channel_ map (gvc-channel- map.c:287) get_sink_ input_info_ cb (gvc-mixer- control. c:886) get_sink_ input_info_ callback (introspect.c:1028) packet_ callback (context.c:357) libpulse- mainloop- glib.so. 0.0.4) context_ dispatch (gmain.c:1960) context_ iterate (gmain.c:2591)
==12744== 122,531,944 bytes in 373,573 blocks are still reachable in loss record 6,971 of 6,971
==12744== at 0x4024C1C: malloc (vg_replace_
==12744== by 0x45972E3: g_malloc (gmem.c:131)
==12744== by 0x45AD418: g_slice_alloc (gslice.c:824)
==12744== by 0x45AD714: g_slice_alloc0 (gslice.c:833)
==12744== by 0x44FD8F6: g_type_
==12744== by 0x44E2747: g_object_
==12744== by 0x44E3707: g_object_newv (gobject.c:1171)
==12744== by 0x44E4589: g_object_new_valist (gobject.c:1323)
==12744== by 0x44E470D: g_object_new (gobject.c:1086)
==12744== by 0x80515FE: gvc_channel_
==12744== by 0x8057552: _pa_context_
==12744== by 0x452DB6C: context_
==12744== by 0x4C6CEA4: run_action (pdispatch.c:274)
==12744== by 0x4C6D475: pa_pdispatch_run (pdispatch.c:326)
==12744== by 0x4525148: pstream_
==12744== by 0x4C726E7: do_something (pstream.c:816)
==12744== by 0x4C5D11D: callback (iochannel.c:119)
==12744== by 0x4511F32: ??? (in /usr/lib/
==12744== by 0x458EE87: g_main_
==12744== by 0x459272F: g_main_
==12744== by 0x4592B9E: g_main_loop_run (gmain.c:2799)
==12744== by 0x418D418: gtk_main (gtkmain.c:1218)
==12744== by 0x804EEF0: main (applet-main.c:92)
==12744==
==12744== LEAK SUMMARY:
==12744== definitely lost: 14,792 bytes in 23 blocks
==12744== indirectly lost: 19,683 bytes in 540 blocks
==12744== possibly lost: 46,340 bytes in 1,836 blocks
==12744== still reachable: 157,160,155 bytes in 1,524,594 blocks
==12744== suppressed: 11,664 bytes in 266 blocks
And in gsd:
==12804== 122,420,096 bytes in 373,232 blocks are possibly lost in loss record 5,433 of 5,433 malloc. c:195) create_ instance (gtype.c:1654) constructor (gobject.c:1383) map_new_ from_pa_ channel_ map (gvc-channel- map.c:287) get_sink_ input_info_ cb (gvc-mixer- control. c:886) get_sink_ input_info_ callback (introspect.c:1028) packet_ callback (context.c:357) libpulse- mainloop- glib.so. 0.0.4) context_ dispatch (gmain.c:1960) context_ iterate (gmain.c:2591)
==12804== at 0x4024C1C: malloc (vg_replace_
==12804== by 0x48702E3: g_malloc (gmem.c:131)
==12804== by 0x4886418: g_slice_alloc (gslice.c:824)
==12804== by 0x4886714: g_slice_alloc0 (gslice.c:833)
==12804== by 0x481C8F6: g_type_
==12804== by 0x4801747: g_object_
==12804== by 0x4802707: g_object_newv (gobject.c:1171)
==12804== by 0x4803589: g_object_new_valist (gobject.c:1323)
==12804== by 0x480370D: g_object_new (gobject.c:1086)
==12804== by 0x651BA2E: gvc_channel_
==12804== by 0x6521382: _pa_context_
==12804== by 0x5CF2B6C: context_
==12804== by 0x5D41EA4: run_action (pdispatch.c:274)
==12804== by 0x5D42475: pa_pdispatch_run (pdispatch.c:326)
==12804== by 0x5CEA148: pstream_
==12804== by 0x5D476E7: do_something (pstream.c:816)
==12804== by 0x5D3211D: callback (iochannel.c:119)
==12804== by 0x5CD7F32: ??? (in /usr/lib/
==12804== by 0x4867E87: g_main_
==12804== by 0x486B72F: g_main_
==12804== by 0x486BB9E: g_main_loop_run (gmain.c:2799)
==12804== by 0x417A418: gtk_main (gtkmain.c:1218)
==12804== by 0x804B9AD: main (main.c:489)
==12804==
==12804== LEAK SUMMARY:
==12804== definitely lost: 7,376 bytes in 584 blocks
==12804== indirectly lost: 28,244 bytes in 2,353 blocks
==12804== possibly lost: 149,360,130 bytes in 1,495,604 blocks
==12804== still reachable: 7,059,820 bytes in 13,284 blocks
==12804== suppressed: 9,360 bytes in 221 blocks
gvc_channel_ map_new_ from_pa_ channel_ map allocates a channel map every time an applications creates a pulseaudio sink. The map ends up stored in a hash table (in update_sink_input in gvc-mixer- control. c). When the application closes the sink, the channel map is not freed. Eventually the hash table grows very large. This is made far worse by misbehaving apps which open and close the sink repeatedly, such as in my video. Valgrind does not see the memory as lost because it is still reachable through the hash table.