首页 > 解决方案 > 为什么我在一个什么都不做的程序中有内存泄漏(在 mac OS 10.13.6 上使用 Valgind)?

问题描述

我刚刚用brew在我的macbook上安装了valgrind,我用这个测试了它:

int main(void)
{
    return (0);
}

这是命令:

valgrind --tool=memcheck --leak-check=full ./test_leaks

和输出:

==736== Memcheck, a memory error detector
==736== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==736== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==736== Command: ./test_leaks
==736==
==736==
==736== HEAP SUMMARY:
==736==     in use at exit: 18,245 bytes in 162 blocks
==736==   total heap usage: 183 allocs, 21 frees, 26,693 bytes allocated
==736==
==736== 64 bytes in 1 blocks are definitely lost in loss record 14 of 39
==736==    at 0x1000AB6EA: calloc (in /usr/local/Cellar/valgrind/3.14.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==736==    by 0x100758B9A: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100758C50: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100758C50: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x10075732B: _read_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100755A9D: map_images_nolock (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1007684E0: map_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100006C64: dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) (in /usr/lib/dyld)
==736==    by 0x100006E39: dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) (in /usr/lib/dyld)
==736==    by 0x10022071D: _dyld_objc_notify_register (in /usr/lib/system/libdyld.dylib)
==736==    by 0x100755073: _objc_init (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1001AAB34: _os_object_init (in /usr/lib/system/libdispatch.dylib)
==736==
==736== 64 bytes in 1 blocks are definitely lost in loss record 15 of 39
==736==    at 0x1000AB6EA: calloc (in /usr/local/Cellar/valgrind/3.14.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==736==    by 0x100758B9A: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100758C50: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100758C50: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100758C50: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x10075732B: _read_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100755A9D: map_images_nolock (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1007684E0: map_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100006C64: dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) (in /usr/lib/dyld)
==736==    by 0x100006E39: dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) (in /usr/lib/dyld)
==736==    by 0x10022071D: _dyld_objc_notify_register (in /usr/lib/system/libdyld.dylib)
==736==    by 0x100755073: _objc_init (in /usr/lib/libobjc.A.dylib)
==736==
==736== 64 bytes in 1 blocks are definitely lost in loss record 16 of 39
==736==    at 0x1000AB6EA: calloc (in /usr/local/Cellar/valgrind/3.14.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==736==    by 0x100758B9A: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100758C68: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100758C50: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100758C50: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100758C50: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x10075732B: _read_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100755A9D: map_images_nolock (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1007684E0: map_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100006C64: dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) (in /usr/lib/dyld)
==736==    by 0x100006E39: dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) (in /usr/lib/dyld)
==736==    by 0x10022071D: _dyld_objc_notify_register (in /usr/lib/system/libdyld.dylib)
==736==
==736== 64 bytes in 1 blocks are definitely lost in loss record 17 of 39
==736==    at 0x1000AB6EA: calloc (in /usr/local/Cellar/valgrind/3.14.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==736==    by 0x100758B9A: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100758C68: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100758C50: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100758C50: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x10075732B: _read_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100755A9D: map_images_nolock (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1007684E0: map_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100006C64: dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) (in /usr/lib/dyld)
==736==    by 0x100006E39: dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) (in /usr/lib/dyld)
==736==    by 0x10022071D: _dyld_objc_notify_register (in /usr/lib/system/libdyld.dylib)
==736==    by 0x100755073: _objc_init (in /usr/lib/libobjc.A.dylib)
==736==
==736== 72 bytes in 3 blocks are possibly lost in loss record 18 of 39
==736==    at 0x1000AB6EA: calloc (in /usr/local/Cellar/valgrind/3.14.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==736==    by 0x1007557C2: map_images_nolock (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1007684E0: map_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100006C64: dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) (in /usr/lib/dyld)
==736==    by 0x100006E39: dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) (in /usr/lib/dyld)
==736==    by 0x10022071D: _dyld_objc_notify_register (in /usr/lib/system/libdyld.dylib)
==736==    by 0x100755073: _objc_init (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1001AAB34: _os_object_init (in /usr/lib/system/libdispatch.dylib)
==736==    by 0x1001AAB1B: libdispatch_init (in /usr/lib/system/libdispatch.dylib)
==736==    by 0x1000B99C2: libSystem_initializer (in /usr/lib/libSystem.B.dylib)
==736==    by 0x100018AC5: ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==736==    by 0x100018CF5: ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==736==
==736== 80 (32 direct, 48 indirect) bytes in 1 blocks are definitely lost in loss record 19 of 39
==736==    at 0x1000AB2FE: malloc_zone_malloc (in /usr/local/Cellar/valgrind/3.14.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==736==    by 0x100757ABF: NXCreateHashTableFromZone (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100757A6E: NXCreateHashTable (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100757948: NXCreateMapTableFromZone (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1007578D3: NXCreateMapTable (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100756394: __sel_registerName(char const*, int, int) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100756096: sel_init (in /usr/lib/libobjc.A.dylib)
==736==    by 0x10075598C: map_images_nolock (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1007684E0: map_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100006C64: dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) (in /usr/lib/dyld)
==736==    by 0x100006E39: dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) (in /usr/lib/dyld)
==736==    by 0x10022071D: _dyld_objc_notify_register (in /usr/lib/system/libdyld.dylib)
==736==
==736== 144 (32 direct, 112 indirect) bytes in 1 blocks are definitely lost in loss record 22 of 39
==736==    at 0x1000AB2FE: malloc_zone_malloc (in /usr/local/Cellar/valgrind/3.14.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==736==    by 0x100757A9E: NXCreateHashTableFromZone (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100757A6E: NXCreateHashTable (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100757948: NXCreateMapTableFromZone (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1007578D3: NXCreateMapTable (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100756394: __sel_registerName(char const*, int, int) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100756096: sel_init (in /usr/lib/libobjc.A.dylib)
==736==    by 0x10075598C: map_images_nolock (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1007684E0: map_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100006C64: dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) (in /usr/lib/dyld)
==736==    by 0x100006E39: dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) (in /usr/lib/dyld)
==736==    by 0x10022071D: _dyld_objc_notify_register (in /usr/lib/system/libdyld.dylib)
==736==
==736== 192 bytes in 3 blocks are definitely lost in loss record 23 of 39
==736==    at 0x1000AB6EA: calloc (in /usr/local/Cellar/valgrind/3.14.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==736==    by 0x100758B9A: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100758C50: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x10075732B: _read_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100755A9D: map_images_nolock (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1007684E0: map_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100006C64: dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) (in /usr/lib/dyld)
==736==    by 0x100006E39: dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) (in /usr/lib/dyld)
==736==    by 0x10022071D: _dyld_objc_notify_register (in /usr/lib/system/libdyld.dylib)
==736==    by 0x100755073: _objc_init (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1001AAB34: _os_object_init (in /usr/lib/system/libdispatch.dylib)
==736==    by 0x1001AAB1B: libdispatch_init (in /usr/lib/system/libdispatch.dylib)
==736==
==736== 192 bytes in 3 blocks are definitely lost in loss record 24 of 39
==736==    at 0x1000AB6EA: calloc (in /usr/local/Cellar/valgrind/3.14.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==736==    by 0x100758B9A: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100758C68: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100758C50: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x10075732B: _read_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100755A9D: map_images_nolock (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1007684E0: map_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100006C64: dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) (in /usr/lib/dyld)
==736==    by 0x100006E39: dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) (in /usr/lib/dyld)
==736==    by 0x10022071D: _dyld_objc_notify_register (in /usr/lib/system/libdyld.dylib)
==736==    by 0x100755073: _objc_init (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1001AAB34: _os_object_init (in /usr/lib/system/libdispatch.dylib)
==736==
==736== 3,264 bytes in 51 blocks are definitely lost in loss record 37 of 39
==736==    at 0x1000AB6EA: calloc (in /usr/local/Cellar/valgrind/3.14.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==736==    by 0x100758B9A: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100758C68: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x10075732B: _read_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100755A9D: map_images_nolock (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1007684E0: map_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100006C64: dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) (in /usr/lib/dyld)
==736==    by 0x100006E39: dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) (in /usr/lib/dyld)
==736==    by 0x10022071D: _dyld_objc_notify_register (in /usr/lib/system/libdyld.dylib)
==736==    by 0x100755073: _objc_init (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1001AAB34: _os_object_init (in /usr/lib/system/libdispatch.dylib)
==736==    by 0x1001AAB1B: libdispatch_init (in /usr/lib/system/libdispatch.dylib)
==736==
==736== 4,136 (24 direct, 4,112 indirect) bytes in 1 blocks are definitely lost in loss record 39 of 39
==736==    at 0x1000AB2FE: malloc_zone_malloc (in /usr/local/Cellar/valgrind/3.14.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==736==    by 0x100757901: NXCreateMapTableFromZone (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1007578D3: NXCreateMapTable (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100756394: __sel_registerName(char const*, int, int) (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100756096: sel_init (in /usr/lib/libobjc.A.dylib)
==736==    by 0x10075598C: map_images_nolock (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1007684E0: map_images (in /usr/lib/libobjc.A.dylib)
==736==    by 0x100006C64: dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) (in /usr/lib/dyld)
==736==    by 0x100006E39: dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) (in /usr/lib/dyld)
==736==    by 0x10022071D: _dyld_objc_notify_register (in /usr/lib/system/libdyld.dylib)
==736==    by 0x100755073: _objc_init (in /usr/lib/libobjc.A.dylib)
==736==    by 0x1001AAB34: _os_object_init (in /usr/lib/system/libdispatch.dylib)
==736==
==736== LEAK SUMMARY:
==736==    definitely lost: 3,992 bytes in 64 blocks
==736==    indirectly lost: 6,864 bytes in 7 blocks
==736==      possibly lost: 72 bytes in 3 blocks
==736==    still reachable: 32 bytes in 1 blocks
==736==         suppressed: 7,285 bytes in 87 blocks
==736== Reachable blocks (those to which a pointer was found) are not shown.
==736== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==736==
==736== For counts of detected and suppressed errors, rerun with: -v
==736== ERROR SUMMARY: 11 errors from 11 contexts (suppressed: 12 from 12)

为了可读性,只有泄漏:

==736== LEAK SUMMARY:
==736==    definitely lost: 3,992 bytes in 64 blocks
==736==    indirectly lost: 6,864 bytes in 7 blocks
==736==      possibly lost: 72 bytes in 3 blocks
==736==    still reachable: 32 bytes in 1 blocks
==736==         suppressed: 7,285 bytes in 87 blocks

我第一次在我正在处理的项目中使用了 valgrind,但是由于上次它有 0 泄漏(在另一台 Mac 上),我觉得这有点奇怪。我重新安装了 valgrind 几次,尝试了我能想到的最基本的程序,我们到了。

虽然我已经在 mac OS 上编程过,但我对它还是比较陌生。这是正常行为吗?还是我必须以某种方式解决这个问题?

编辑:

所以这需要一些工作,但我终于设法消除了“不需要的”错误。我编写了一个脚本,将命令输入,将其传递给 valgrind,并将生成的每个泄漏存储在抑制文件中。这是 valgrind 在遇到时根本不会显示的已知泄漏列表(有关它的更多信息herethere)。这很hacky,但它解决了我的问题。

这个解决方案显然不是最优的。现在,每次我看到泄漏时,我都必须手动检查它是来自我的程序还是我还没有遇到过的系统库泄漏。

如果有人有一个不那么 hacky 的解决方案,我会很高兴在这里。但是如果你有同样的问题,暂时这里是脚本(小心并首先检查 valsup 文件,特别是如果你的主目录中已经有一个“.valgrindrc”文件)。这包括一个 perl 脚本(您可以在本页末尾找到),它解析 valgrind 输出以获取抑制。

标签: macosmemoryvalgrind

解决方案


推荐阅读