#design-patterns #visual-c #memory-leaks
#шаблоны проектирования #visual-c #утечки памяти
Вопрос:
Следующая тривиальная демонстрация записывает «утечку памяти: 8» на консоль, для меня.
Если я закомментирую строку getInstance() в main(), он пишет «утечка памяти: 0».
Еще более странно, если я закомментирую строку «void * dummy = nullptr;» в TestSingleton, я получаю «утечка памяти: 1».
Что в мире происходит?
Здесь происходит только одно выделение кучи, и оно удаляется. Итак, как это происходит утечка?
#include <iostream>
#include <crtdbg.h>
#include <conio.h>
struct TestSingleton
{
static TestSingleton * instance;
void* dummy = nullptr;
static TestSingleton amp; GetInstance()
{
if (!instance) instance = new TestSingleton();
return *instance;
}
static void Destroy()
{
delete instance;
instance = nullptr;
}
};
TestSingleton* TestSingleton::instance = nullptr;
int main()
{
_CrtMemState state1;
_CrtMemState state2;
_CrtMemState state3;
_CrtMemCheckpoint(amp;state1);
{
TestSingletonamp; t = TestSingleton::GetInstance();
TestSingleton::Destroy();
}
_CrtMemCheckpoint(amp;state2);
_CrtMemDifference(amp;state3, amp;state1, amp;state2);
size_t difference = state3.lTotalCount;
std::cout << "memory leak: " << difference << "n";
char dmy = getchar();
return 0;
}
Комментарии:
1. Я могу объяснить получение
1
: размер экземпляра пустого класса (без членов) не может быть равен 0. Я думаю, это зависит от компилятора, и MS использует1
. An8
— это размер указателя void в 64-разрядной сборке.2. Но я удаляю экземпляр. Не должно быть никакого экземпляра. И статический указатель на экземпляр существовал до первой контрольной точки кучи. Он должен быть загружен с помощью nullptr перед запуском любого кода.
Ответ №1:
Я думаю, что я понял это, или, по крайней мере, я обнаружил подсказку. При связывании с средой выполнения отладки из-за настроек проекта, связанных с библиотеками, с которыми я связываюсь, я в конечном итоге получаю CrtDbgFlag, установленный таким образом, что выделения не освобождаются. Проблема исчезает после сборки в режиме выпуска, и она исчезает в режиме отладки, если я вызываю _CrtSetDbgFlag(0) перед выделением и освобождением.
Если я делаю что-либо из этого, эта программа сообщает «утечка памяти: 0».
Комментарии:
1. О нет, но теперь он делает это снова в режиме отладки, установки CrtDbgFlag в 0 недостаточно.