Утечка памяти в C ++ не отображается должным образом

я использую _CrtDumpMemoryLeaks (); из stdlib.h и crtdbg.h для обнаружения утечек памяти, но я заметил кое-что странное в моем коде.

Если я сделаю:

int _tmain(int argc, _TCHAR* argv[])
{
MyClass* myClass = new MyClass();
_CrtDumpMemoryLeaks(); //I get a memory leak warning
}

Однако, если я сделаю:

class MyClass
{
public:
char* NewChar();
};
char* MyClass::NewChar()
{
char* test = new char[100];
return test;
}

MyClass myClass; //Globally declared
int _tmain(int argc, _TCHAR* argv[])
{
char* charPointer = myClass.NewChar();
_CrtDumpMemoryLeaks(); //No warnings
}

Я не должен получить предупреждение, так как моя программа вышла (сразу после _CrtDumpMemoryLeaks ()) а еще был новый символ, который не был удален?

Как я могу обнаружить эти утечки памяти?

Также, используя тот же пример выше, если я добавлю код:

char* anotherPointer = charPointer; //previously filled
delete[] anotherPointer;

Будет ли это удалить новый символ из класса, предотвращая утечки памяти, или я должен вызвать delete on charPointer также?

0

Решение

Если вы хотите отловить (или прилично попытаться отловить) глобальные утечки объектов, попробуйте установить флаг отладки CRT _CRTDBG_LEAK_CHECK_DF в начале основного. Флаг заставляет сброс обнаруженных утечек после глобальные деструкторы.

Чтобы ответить на ваши вопросы:

Разве я не должен получить предупреждение, так как моя программа закрылась (сразу после _CrtDumpMemoryLeaks ()), и все еще был новый символ, который не был удален?

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

Как я могу обнаружить эти утечки памяти?

Они должны быть правильно обнаружены при условии, что вы используете CRT отладки и имеете _Crt настройка конфигурации правильно, что это в основном является по умолчанию.


Следующий код устанавливает _Crt система дампов для выгрузки всех объектов по требованию и непосредственно перед окончательным выходом (после main() закончен и глобальные статики уничтожены).

class MyLeak
{
public:
MyLeak() { new unsigned char[1024]; }

char * NewChar() { return new char[1024]; }
};

MyLeak myLeak;
int main(int argc, char *argv[])
{
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
_CrtSetDbgFlag(tmpFlag);

_CrtMemState ms = {0};
_CrtMemCheckpoint(&ms);

char *ptr = myLeak.NewChar();
_CrtMemDumpAllObjectsSince(&ms);

OutputDebugString("Exiting main()\n");
return EXIT_SUCCESS;
}

Отладочный выходной журнал

Dumping objects ->
{69} normal block at 0x000000000048B800, 1024 bytes long.
Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
Exiting main()
Detected memory leaks!
Dumping objects ->
{69} normal block at 0x000000000048B800, 1024 bytes long.
Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
{68} normal block at 0x000000000048B390, 1024 bytes long.
Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

Обратите внимание, что первый дамп записывает только внутреннее распределение, поскольку я использовал контрольную точку, а затем вызов dump-Since. Второй дамп (вызывается после main() закончено) все еще записывает их обоих, так как они оба выдающиеся.

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

2

Другие решения

Думаю об этом. Глобальная переменная myClass имеет статическую продолжительность хранения. Он будет уничтожен после закрывающей скобки main когда программа заканчивается. _CrtDumpMemoryLeaks() не может утвердительно определить утечку как деструктор MyClass еще не (правильно) был вызван.

0

Я не должен получить предупреждение, так как моя программа закрылась (сразу после_CrtDumpMemoryLeaks ())

Да, вы должны получить предупреждение, но не из-за выхода, …

а еще был новый символ, который не был удален?

…но из-за этого, т. е. потому что массив символов это не было удалено.

Как я могу обнаружить эти утечки памяти?

Вы уверены, что скомпилировали программу с _DEBUG #defined? Если вы это сделали, это должно быть обнаружено. (Я не могу проверить себя сейчас и не использовал это целую вечность, поэтому я не могу ручаться за это.)

Также, используя тот же пример выше, если я добавлю код:

char* anotherPointer = charPointer; //previously filled
delete [] anotherPointer; `

Будет ли это удалять новый символ изнутри класса, предотвращая утечки памяти, или я должен также вызвать delete в charPointer?

Это удалит динамически распределенный массив символов. После этого charPointer это свисающий указатель, которые нельзя использовать больше — ни разыменовывать, ни удалять [] ‘d. (То же самое относится и к anotherPointer.) Повторное удаление удаленного массива, через тот же указатель или другую переменную, не допускается и вызывает Неопределенное поведение.

0

Вы связываетесь с отладочными библиотеками? Если вы этого не сделаете, вы не будете получать сообщения о неосвобожденных блоках памяти. Подсказка: используйте параметр / MDd.

Обратите внимание, что вопреки тому, что предлагает имя функции, все, что она делает, это печатает список блоков памяти, которые вы еще не освободили. Вызывая его в конце main (), вы заставляете его отчитываться о блоках, которые вы явно разместили, но явно не освободили. Поэтому, если у вас есть одноэлементные объекты, размещаемые динамически, они будут сообщаться как утечка, тогда как вы вполне законно можете освободить их, используя функцию, подключенную через механизм _atexit ().

0
По вопросам рекламы [email protected]