C ++中的“仍然可访问”和“可能丢失”块的valgrind输出未引用我的源代码

c++ boost memory-leaks valgrind

1033 观看

1回复

672 作者的声誉

我很难确定我的代码在哪里出现内存泄漏。

我运行的valgrind命令:

valgrind --leak-check=full --log-file=vg1.log --show-leak-kinds=all --leak-resolution=low --track-origins=yes --leak-check-heuristics=all ./enalu_dbg

和输出

==22866== Memcheck, a memory error detector
==22866== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==22866== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==22866== Command: ./enalu_dbg
==22866== Parent PID: 21933
==22866== 
==22866== 
==22866== HEAP SUMMARY:
==22866==     in use at exit: 47,252 bytes in 240 blocks
==22866==   total heap usage: 288 allocs, 48 frees, 55,138 bytes allocated
==22866== 
==22866== 4 bytes in 1 blocks are still reachable in loss record 1 of 23
==22866==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22866==    by 0x77018CD: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0)
==22866==    by 0x7701D28: g_private_get (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0)
==22866==    by 0x76DB20C: g_slice_alloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0)
==22866==    by 0x76AF17D: g_hash_table_new_full (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0)
==22866==    by 0x76CF494: g_quark_from_static_string (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0)
==22866==    by 0x74314AB: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0)
==22866==    by 0x4010139: call_init.part.0 (dl-init.c:78)
==22866==    by 0x4010222: call_init (dl-init.c:36)
==22866==    by 0x4010222: _dl_init (dl-init.c:126)
==22866==    by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so)

...

==22866== 184 bytes in 1 blocks are possibly lost in loss record 13 of 23
==22866==    at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22866==    by 0x76C56AE: g_realloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0)
==22866==    by 0x7451618: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0)
==22866==    by 0x74560D4: g_type_register_static (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0)
==22866==    by 0x7442DE6: g_param_type_register_static (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0)
==22866==    by 0x74449AB: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0)
==22866==    by 0x74315E9: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0)
==22866==    by 0x4010139: call_init.part.0 (dl-init.c:78)
==22866==    by 0x4010222: call_init (dl-init.c:36)
==22866==    by 0x4010222: _dl_init (dl-init.c:126)
==22866==    by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so)
==22866== 

...

==22866== 6,028 bytes in 60 blocks are still reachable in loss record 21 of 23
==22866==    at 0x4C2CC70: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22866==    by 0x76C5668: g_malloc0 (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0)
==22866==    by 0x74514D9: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0)
==22866==    by 0x74560D4: g_type_register_static (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0)
==22866==    by 0x7442DE6: g_param_type_register_static (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0)
==22866==    by 0x744423A: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0)
==22866==    by 0x74315E9: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0)
==22866==    by 0x4010139: call_init.part.0 (dl-init.c:78)
==22866==    by 0x4010222: call_init (dl-init.c:36)
==22866==    by 0x4010222: _dl_init (dl-init.c:126)
==22866==    by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so)
==22866== 
==22866== 10,360 bytes in 5 blocks are still reachable in loss record 22 of 23
==22866==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22866==    by 0x8B16E9A: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==22866==    by 0x8B15ACE: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==22866==    by 0x8B17585: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==22866==    by 0x8AC9508: ??? (in /usr/lib/x86_64-linux-gnu/libpixman-1.so.0.30.2)
==22866==    by 0x4010139: call_init.part.0 (dl-init.c:78)
==22866==    by 0x4010222: call_init (dl-init.c:36)
==22866==    by 0x4010222: _dl_init (dl-init.c:126)
==22866==    by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so)
==22866== 
==22866== 16,600 bytes in 4 blocks are still reachable in loss record 23 of 23
==22866==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22866==    by 0x76C5610: g_malloc (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0)
==22866==    by 0x76CF445: g_quark_from_static_string (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0)
==22866==    by 0x74314AB: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.4002.0)
==22866==    by 0x4010139: call_init.part.0 (dl-init.c:78)
==22866==    by 0x4010222: call_init (dl-init.c:36)
==22866==    by 0x4010222: _dl_init (dl-init.c:126)
==22866==    by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so)
==22866== 
==22866== LEAK SUMMARY:
==22866==    definitely lost: 0 bytes in 0 blocks
==22866==    indirectly lost: 0 bytes in 0 blocks
==22866==      possibly lost: 1,352 bytes in 18 blocks
==22866==    still reachable: 45,900 bytes in 222 blocks
==22866==                       of which reachable via heuristic:
==22866==                         newarray           : 1,536 bytes in 16 blocks
==22866==         suppressed: 0 bytes in 0 blocks
==22866== 
==22866== For counts of detected and suppressed errors, rerun with: -v
==22866== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)

显示的大多数记录(但1)是“仍可到达的块”。我读到这些可能是由于池重新分配延迟所致。也就是说,在main(argc,argv){}函数终止后,容器(例如vectors,我大量使用)的释放。

但是,肯定有问题,因为在执行大约8-9个小时后,我清楚地看到可执行文件使用的内存比开始时要多(在我的电脑中,开始时使用的内存为0.6%,而在8小时后,它使用了大约6 %)。

问题是这些都是隐秘的消息-绝对没有源于我的源文件。正如我在这里阅读的“ _dl *”调用与linux loader有关。那么,如何确定问题的根源呢?

我应该补充一点,此代码使用

  1. 1 + 3个线程(用于所有阻止操作,即从stdin和串行端口读取并将数据写入文件),
  2. Boost库(尤其是循环缓冲区),以及
  3. gsl库。

但是,我是从小的概念证明部分构建代码的,这些部分并没有显示valgrind中的任何错误/警告。

另外,我的代码中只有很少数量的指向类对象的指针,我已delete在各自的析构函数中对其进行了验证。

作者: nass 的来源 发布者: 2016 年 1 月 6 日

回应 (1)


6

68013 作者的声誉

决定

原始分配调用来自共享库初始化代码,该共享库初始化代码在与您的应用程序链接的共享库在运行时加载时执行,通常在任何应用程序代码实际运行之前执行。这就是为什么在回溯中看不到代码的原因。它甚至还没有运行。

要查找的关键符号是_dl_init,是共享库初始化的入口点。往上游看可以告诉您正在初始化哪个库。在您的情况下,它是一堆Gnome库和一个名为“ libpixman”的库。

共享库还具有清除功能,该功能在共享库被卸载时被调用。

组织良好的共享库将使用共享库清除功能来有序地取消分配其在启动时分配的所有内存。不幸的是,这种对细节的疏忽是可悲的普遍现象:共享库从堆中为共享库的内部静态表分配了一堆内存,而无需在卸载共享库时费心去分配该内存。

这不太可能造成您在应用程序运行时观察到的内存泄漏,除非我稍后会提到一种情况。我的经验是,这种草率的分配做法仅用于共享库在加载时分配一次的静态表。这里的想法是,不必自己进行明确的清理,因为当进程退出时,库只会被卸载一次。

可悲的是,开辟这类角落的开发人员从未听说过dlopen()和dlclose()。这使得大型应用程序无法仅在需要时才按需加载共享库,然后再卸载,直到再次需要。

因此,除非您的应用程序代码重复dlopen(或重复)dlclose所有这些Gnome库和libpixman,否则您将不得不继续寻找其他地方的泄漏。您应该继续阅读并使用valgrind的抑制文件,以抑制其输出中的这种烦人的噪音。

作者: Sam Varshavchik 发布者: 06.01.2016 11:08
32x32