Подтвердить что ты не робот

Обнаружение утечки памяти GCC эквивалентно Microsoft crtdbg.h?

После многих лет работы над библиотекой С++ общего назначения с использованием компилятора Microsoft MSVC в Visual Studio мы переносим его в Linux/Mac OS X (молимся за нас). Я привык и очень люблю простой механизм обнаружения утечки памяти в MSVC:

#ifdef DEBUG
    #define _CRTDBG_MAP_ALLOC
    #define NEW   new( _NORMAL_BLOCK, __FILE__, __LINE__)
    #include <stdlib.h>
    #include <crtdbg.h>
#else
    #define NEW   new
#endif

Каждое выделение памяти выполняется с использованием этого НОВОГО макроса. Всякий раз, когда процесс, использующий нашу библиотеку, завершается, любые утечки памяти (блоки, которые не были выделены) сообщаются на консоли вместе с файлом и строкой #, где первоначально была выделена память.

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

Теперь, когда мы переходим в мир GCC, я обнаружил, что инструменты обнаружения утечки памяти, многие из которых довольно сложны, требуют, чтобы я явно указывал, что я в режиме поиска утечки. Моя IDE - это Xcode, и я изучил некоторые инструменты выделения/утечки (например, инструменты и MallocDebug), но я признаю, что не потратил времени, чтобы полностью окунуться в них. Я все время откладываю на то, что на самом деле мне нужно указать, что я ищу утечку раньше времени, вместо того, чтобы автоматически получать уведомление об этом.

Я использую Xcode 3.2, и я слышу, что теперь есть отличная интеграция со средством статического анализа, но опять же я не рассматривал это. Я ищу какое-то представление о моих вариантах. Есть ли сопоставимый механизм, встроенный в GCC и/или Xcode? Есть ли простая сторонняя библиотека или инструмент, который выполняет те самые основные функции, которые я знаю и люблю? Или я должен сосать его и узнать новый способ делать что-то?

4b9b3361

Ответ 2

У вас есть несколько доступных вам вариантов.

Во-первых, и наиболее популярно вы можете запускать свое приложение под такими инструментами, как Valgrind. Это должно указывать на ряд нарушений памяти, таких как чтение и запись указателей NULL, а также утечки памяти. В наборе Valgrind имеется ряд инструментов, поэтому обязательно проверьте их.

Во-вторых, вы всегда можете использовать библиотеку, которая использует трюк LD_PRELOAD. В принципе, трюк LD_PRELOAD позволяет использовать DLL-инъекцию, а это значит, что инструменты могут быть созданы, чтобы отслеживать использование вашей памяти в приложении без каких-либо изменений. Вы найдете такие инструменты, как dmalloc и efence, чтобы быть достаточно обширными в средствах для отладки, которые они предлагают.

Наконец, последние выпуски GCC включали инструмент Mudflap. Это в основном использует функцию инструментария для обертывания вызовов вокруг одних и тех же функций памяти, которые dmalloc, efence и Valgrind. Программа будет заметно медленнее и может быть настроена во время выполнения, хотя по-прежнему выглядит так, что у нее большой потенциал.

Я использовал все три и нашел Valgrind очень полезным. Мне также очень хотелось использовать Mudflap, хотя я еще не смог.

Ответ 3

Вы также можете найти полезную переменную среды MALLOC_CHECK_.

Из справочной страницы malloc (3):

Последние версии Linux libc (позже 5.4.23) и glibc (2.x) включают реализацию malloc(), которая настраивается через переменные среды. Когда установлен MALLOC_CHECK_, используется специальная (менее эффективная) реализация, которая предназначена для толерантности к простым ошибкам, таким как двойные вызовы free() с одним и тем же аргументом или переполнения одного байта (ошибки by-by-one). Тем не менее, не все такие ошибки могут быть защищены, и могут возникнуть утечки памяти. Если для параметра MALLOC_CHECK_ установлено значение 0, любое обнаруженное повреждение кучи тихо игнорируется; если установлено значение 1, на stderr выводится диагностическое сообщение; если установлено значение 2, то прерывание (3) вызывается немедленно; если установлено значение 3, диагностическое сообщение печатается на stderr, и программа прерывается. Использование ненулевого значения MALLOC_CHECK_ может быть полезно, поскольку в противном случае авария может произойти намного позже, и истинную причину проблемы тогда очень сложно отследить.

Ответ 4

Возможно, вы можете использовать сборщик мусора Boehm в качестве средства обнаружения утечек:

http://www.hpl.hp.com/personal/Hans_Boehm/gc/leak.html

С сайта:

#include "leak_detector.h"

main() {
    int *p[10];
    int i;
    /* GC_find_leak = 1; for new collector versions not     */
    /* compiled with -DFIND_LEAK.               */
    for (i = 0; i < 10; ++i) {
    p[i] = malloc(sizeof(int)+i);
    }
    for (i = 1; i < 10; ++i) {
    free(p[i]);
    }
    for (i = 0; i < 9; ++i) {
    p[i] = malloc(sizeof(int)+i);
    }
    CHECK_LEAKS();
}   

(вы получаете уведомление через stderr)

Ответ 5

Я не знаю ничего "встроенного", который делает то, что вы описываете, но похоже, что было бы очень сложно "перевернуть свою" версию. Вы просто хотите, чтобы ваша новая отладочная запись записывала указатель, файл и строку в map<void*, AllocationInfo>, где ключ является выделенным указателем, а значение (AllocationInfo) - это некоторая структура, которая содержит имя файла, номер строки и т.д. Вы также необходимо определить пользовательский оператор удаления, который проверяет карту для удаляемого указателя. Если найдено, эта запись удаляется с карты. Затем во время выключения процесса вы выбрасываете содержимое карты.

Я нашел страницу, где кто-то описывает свою собственную доморощенную систему, которая работает так.

Ответ 6

У меня была такая же проблема, когда мы начали переносить на Mac. "Run with performance tool → Leaks" был единственным, что я нашел, и я менее взволнован этим... по крайней мере, по сравнению с CRTDEBUG. Я понимаю, что есть некоторые варианты (как описано здесь здесь), но в конце концов, поскольку мы являемся мультиплатформой, мы используем Windows для поиска утечек.

Так как вы упоминаете статический анализатор. Мы потратили некоторое время, пытаясь разобраться в горячем состоянии, чтобы запустить его, пока не обнаружили, что он только C, но не С++