утечка памяти: не мог повредиться на числе выделения памяти

Я пытаюсь определить местоположение проблемы утечки памяти.

Мой проект является основанным на ATL диалоговым проектом, который использует DirectShow и стандартную библиотеку.

Я получаю в общей сложности 45 утечек памяти в своей программе, все 24 байта каждый.

У меня есть #define'd _CRTDBG_MAP_ALLOC и т.д. в моем stdafx.h, наряду с DEBUG_NEW для получения номеров документов и номеров строки для каждой из утечек памяти.

Однако никакие номера строки файла не печатаются. Блоки памяти являются всеми "нормальными" блоками и похожи на это:

{180} normal block at 0x003E6008, 24 bytes long. Data: <  >  _>   > W   > A0 AE 3E 00 B0 5F 3E 00 A0 AE 3E 00 57 00 00 00 

Я попытался добавить следующую строку к запуску _tWinMain ()

_CrtSetBreakAlloc(180);

для повреждения на выделении, но отладчик не повреждается вообще.

Кто-либо может дать мне понимание, как я мог бы разыскать неуловимые утечки памяти?

Наконец, вот мой _tWinMain () - я называю _CrtDumpMemoryLeaks () непосредственно перед выходом.

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow){
    _CrtSetBreakAlloc(180);

    HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
    ATLASSERT(SUCCEEDED(hRes));


    ::DefWindowProc(NULL, 0, 0, 0L);
    AtlInitCommonControls(ICC_BAR_CLASSES);

    //HINSTANCE hInstRich = ::LoadLibrary(CRichEditCtrl::GetLibraryName());

    hRes = _Module.Init(NULL, hInstance);
    ATLASSERT(SUCCEEDED(hRes));

    int nRet = Run(lpstrCmdLine, nCmdShow);

    _Module.Term();
    ::CoUninitialize();

    _CrtDumpMemoryLeaks();

    return nRet;
}
5
задан Jerry Coffin 25 June 2010 в 14:28
поделиться

2 ответа

Два предложения.

Во-первых, то, что создается до начала main (или эквивалентного), уничтожается после завершения main. Вызов _CrtDumpMemoryLeaks в конце main может дать ложные срабатывания. (Или это ложные отрицательные результаты?) Деструкторы глобальных объектов еще не запущены, а обратные вызовы atexit еще не запущены, поэтому вывод утечки будет включать выделения, которые просто еще не были правильно освобождены.

(Я подозреваю, что именно поэтому ваши глобальные объекты оказываются в утечке. Вполне возможно, что в коде все в порядке, и он вполне может очищаться должным образом - просто код очистки еще не запущен, когда вызывается _CrtDumpMemoryLeaks. )

Что вам нужно сделать вместо этого, так это направить библиотеку времени выполнения на вызов _CrtDumpMemoryLeaks для вас, в самом конце, после завершения всех atexit обратных вызовов и деструкторов глобальных объектов. Тогда вы увидите только настоящие утечки. Этот фрагмент поможет. Вставьте его в начало main:

_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)|_CRTDBG_LEAK_CHECK_DF);

Во-вторых, если вышеописанное обнаружит настоящие утечки из того, что выполняется до main, вы можете применить небольшую хитрость, чтобы ваш собственный код выполнялся намного раньше, чем все остальное. Затем вы можете установить _crtBreakAlloc до того, как произойдет выделение. Просто поместите следующий код в собственный файл .cpp:

#include <crtdbg.h>

#ifdef _DEBUG

#pragma warning(disable:4074)//initializers put in compiler reserved initialization area
#pragma init_seg(compiler)//global objects in this file get constructed very early on

struct CrtBreakAllocSetter {
    CrtBreakAllocSetter() {
        _crtBreakAlloc=<allocation number of interest>;
    }
};

CrtBreakAllocSetter g_crtBreakAllocSetter;

#endif//_DEBUG

(Я подозреваю, что код в сегменте init компилятора может выполняться до инициализации stdin и stdout и т.п., и уж точно до создания любых глобальных объектов, поэтому у вас могут возникнуть трудности с выполнением чего-либо более сложного, чем описанное выше! )

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

.
7
ответ дан 14 December 2019 в 08:41
поделиться

У меня была пара глобальных переменных (таблицы поиска, которые возвращали ссылки CString на сообщения об ошибках), которые я удалил из программы. Как только я это сделал - никаких утечек памяти.

Спасибо за ваши комментарии, друзья.

Интересно - мне придется исследовать другой способ реализации поиска ошибок.

Я делал что-то вроде:

CString sError = "error at line x: " + g_map.lookup(hrError);

Карта ошибок реализована как объект, который оборачивает доступ к std::map, и его деструктор работает нормально. Когда я выделяю этот объект карты на куче и удаляю его, он не сообщает об утечках памяти. Возможно, дело в том, как я конкатенирую CString....

0
ответ дан 14 December 2019 в 08:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: