Почему у меня возникают утечки памяти в программе, которая ничего не делает (с Valgind на Mac OS 10.13.6)? - PullRequest
2 голосов
/ 28 марта 2019

Я только что установил valgrind на свой MacBook с Brew, и я проверил это с помощью:

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, я относительно новичок в этом. Это нормальное поведение? Или я должен как-то это исправить?

EDIT:

Так что это заняло немного работы, но мне наконец удалось удалить «нежелательные» ошибки. Я написал скрипт, который принимает команду на вход, пропускает ее через valgrind и сохраняет каждую утечку, сгенерированную в файле подавления. Это список известных утечек, которые valgrind просто не отобразит при обнаружении (больше информации об этом здесь и там ). Это глупо, но это как бы решает мою проблему.

Это решение, однако, не является оптимальным. Теперь каждый раз, когда я увижу утечку, мне придется вручную проверять, происходит ли она из моей программы или это утечка системной библиотеки, с которой я еще не сталкивался.

Если у кого-нибудь есть менее хакерское решение, я буду рад его здесь. Но на данный момент здесь есть сценарий , если у вас есть та же проблема (будьте осторожны и сначала проверьте файл valsup, особенно если у вас уже есть файл .valgrindrc в вашем домашнем каталоге). Это включает в себя сценарий perl (который вы можете найти в конце этой страницы ), который анализирует вывод valgrind для получения подавлений.

...