C поиск утечек памяти

Автор: Эдвард Райт
Перевод: Александр Шаргин
Источник: MSDN
Версия текста: 1.0.2

Введение

Динамическое распределение и освобождение памяти — одна из мощнейших возможностей языка C/C++. Но, как заметил китайский философ Сан Тзю, великая сила может обернуться великой слабостью. Это особенно верно в отношении приложений, написанных на C/C++, где ошибки при работе с памятью относятся к числу самых распространённых. Из них наиболее тонкими и трудными для обнаружения являются утечки памяти, которые возникают, когда память, выделенная программой, никогда не освобождается. Небольшие утечки памяти, возникающие один раз, могут никак не сказаться на работе программы. Однако значительные утечки, накапливающиеся со временем, могут привести к различным неприятным последствиям, начиная с невысокой производительности, и заканчивая полным отказом программы вследствие нехватки памяти. Что ещё хуже, программа, допускающая утечки памяти, может привести к краху совсем другую программу, и пользователь никогда не узнает, в чём состоит истинная причина отказа. Кроме всего перечисленного, даже самая незначительная утечка может свидетельствовать о наличии других серьёзных проблем в вашей программе.

К счастью, отладчик Visual C++ и стандартная библиотека языка C (CRT) предоставляют вам целый набор отличных инструментов для обнаружения и локализации утечек памяти. В этой статье я покажу вам, как ими пользоваться.

Активизация режима обнаружения утечек памяти

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

Директивы #include должны идти в указанном порядке. В противном случае функции, которыми мы воспользуемся, будут работать неправильно. Включая файл crtdbg.h, мы перенаправляем вызовы функций malloc и free на их отладочные версии _malloc_dbg и _free_dbg, которые отслеживают все операции по распределению и освобождению памяти. Перенаправление происходит только в отладочной версии программы (то есть, когда определён символ _DEBUG). В окончательной версии будут использоваться обычные функции malloc и free.

Директива #define непосредственно отображает базовые функции для работы с "кучей" на их отладочные версии. Вставлять её в программу не обязательно, но без неё отчёт об утечках памяти будет менее подробным.

После того, как вы добавили в вашу программу указанные строчки, вы можете получить информацию об утечках памяти, обратившись к функции:

Когда программа выполняется под управлением отладчика, _CrtDumpMemoryLeaks отображает информацию об утечках памяти на вкладке Debug окна Output. Эта информация выглядит примерно так:

Если бы вы не включили в программу директиву #define _CRTDBG_MAP_ALLOC, отчёт выглядел бы так:

Как видите, _CrtDumpMemoryLeaks выдаёт гораздо более полезную информацию, когда символ _CRTDBG_MAP_ALLOC определён. Без него вам выдаются следующие данные:

  • порядковый номер распределения памяти (в фигурных скобках).
  • тип блока (нормальный, клиентский или CRT-блок).
  • адрес блока (в шестнадцатеричном представлении).
  • размер блока в байтах.
  • содержимое первых 16 байт этого блока (также в шестнадцатеричном представлении).

Если _CRTDBG_MAP_ALLOC определён, вам дополнительно показывается имя файла, в котором произошло распределение памяти. После имени файла в скобках содержится номер строки (20 в нашем примере). Если сделать двойной щелчок на строчке, содержащей имя файла и номер строки в нём:

то курсор переместится на строку в файле с исходным кодом программы (в нашем примере строку 20 в файле leaktest.cpp), где произошло распределение памяти. Аналогичного эффекта можно добиться, выделив строчку и нажав F4.

Использование _CrtSetDbgFlag

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

После этого функция _CrtDumpMemoryLeaks будет автоматически вызываться перед завершением работы вашей программы. Вы должны задать оба флага (_CRTDBG_ALLOC_MEM_DF и _CRTDBG_LEAK_CHECK_DF), как это показано выше.

Типы блоков памяти

Как я уже говорил, в информацию об утечках памяти входит тип блока, который может быть нормальным, клиентским или CRT-блоком. На практике вам скорее всего будут встречаться блоки первых двух типов.

  • Нормальный блок (normal block) — это обычный блок, распределяемый вашей программой.
  • Клиентский блок (client block) — особый тип блока, используемый в программах под MFC для объектов, имеющих деструктор. [На самом деле клиентский блок памяти — это блок, для которого определяется пользовательская функция построения отчёта об утечках памяти. В MFC блоки этого типа распределяются для объектов класса, порождённого от CObject. MFC предоставляет функцию построения отчёта _AfxCrtDumpClient (описана в файле dumpinit.cpp), которая вызывает виртуальную функцию CObject::Dump для объекта, размещённого в клиентском блоке памяти. Это даёт вам возможность переопределить функцию CObject::Dump в производном классе, чтобы выводить содержимое объекта в окне Debug в более удобной для восприятия форме — прим. перев.]
  • CRT-блок (CRT block) — это блок памяти, который CRT распределяет для внутреннего использования. Стандартная библиотека сама заботится об освобождении таких блоков, так что вы вряд ли увидите их в отчёте об утечках памяти. Их наличие может сигнализировать о серьёзных проблемах (например, о повреждении CRT). [По умолчанию функция _CrtDumpMemoryLeaks не показывает блоки этого типа. Чтобы их увидеть, необходимо предварительно установить флаг _CRTDBG_CHECK_CRT_DF с помощью функции _CrtSetDbgFlag — прим. перев.]

Существует ещё два типа блоков, которые никогда не попадают в отчёт об утечках памяти:

  • Освобождённый блок (free block) — это блок памяти, который уже освобождён вашей программой.
  • Игнорируемый блок (ignore block) — это блок, который вы специально пометили как абсолютно вас не интересующий.

Установка режима сообщений CRT

По умолчанию _CrtDumpMemoryLeaks выводит свой отчёт об утечках памяти на вкладку Debug окна Output, как это уже описывалось выше. Однако вы можете перенаправить эту информацию в другое место посредством _CrtSetReportMode. И наоборот: если вы используете библиотеку, которая куда-то перенаправляет вывод, вы можете вернуть его в окно Output, используя следующий вызов:

За дополнительной информацией об использовании функции _CrtSetReportMode обратитесь к разделу "_CrtSetReportMode" в документации на Visual C++ (Visual C++ Programmer’s Guide, Run-Time Library Reference, Debug Function Reference).

Установка точки останова на нужном распределении памяти

Имя файла и номер строки в отчёте об утечках памяти указывает вам, где именно в программе был выделен соответствующий блок. Тем не менее, иногда этой информации оказывается недостаточно, чтобы выявить проблему. В процессе выполнения программы одно и то же распределение может происходить множество раз, но приводить к утечкам лишь в некоторых случаях. Поэтому нужно определить не только точку, в которой потерянный блок был выделен, но и при каких условиях произошла утечка. Решить задачу поможет порядковый номер распределения, то самое число, которое выводится в фигурных скобках вслед за именем файла и номером строки в нём (если, конечно, вы включили их отображение). Например, в приведённом ниже отчёте "18" — это порядковый номер распределения. Он означает, что потерянный блок был выделен восемнадцатым по счёту.

CRT учитывает каждый блок, выделенный вашей программой в процессе работы, в том числе и блоки, распределяемые самой CRT и другими библиотеками, такими как MFC. Поэтому блок с порядковым номером n — это n-й блок, распределённый вашей программой, но совсем не обязательно n-й блок, распределённый вашим собственным кодом. Как правило, это не так.

Читайте также:  Как перекинуть видео с компьютера на айпад

Вы можете использовать порядковый номер распределения, чтобы поставить точку останова в точности на то место, где выделяется соответствующий блок. Для этого поставьте обычную точку останова где-нибудь в начале вашей программы. Когда выполнение прервётся в этой точке, вы сможете поставить точку останова на распределение памяти из диалога QuickWatch или из окна Watch. Например, в окне Watch наберите в колонке "Name" имя:

Если вы используете многопоточную версию CRT, размещённую в динамически подключаемой библиотеке (опция /MD), вы должны задать полный контекстный оператор, как показано ниже:

Теперь нажмите RETURN. Отладчик рассчитает значение переменной и разместит его в колонке "Value". Если перед этим вы не ставили точек останова на распределения памяти, значение будет равно -1. Замените его порядковым номером распределения, на котором вы хотите прервать выполнение программы, например, номером 18, чтобы прерваться на распределении, показанном выше.

После того, как вы поставили точку останова на интересующее вас распределение, можно продолжать отладку. Однако будьте осторожны и выполняйте программу в тех же условиях, что и в предыдущий раз, чтобы порядок распределений памяти не изменился. Когда программа прервётся на распределении нужного блока, вы сможете проанализировать содержимое окна Call Stack и любую другую информацию, предоставляемую отладчиком, чтобы определить условия, при которых происходит утечка. Если нужно, вы можете также продолжить выполнение программы, чтобы проследить, что произойдёт с объектом дальше и почему он не освобождается, как положено (тут вам могут пригодиться точки останова по данным).

Хотя в большинстве случаев удобнее ставить точки останова на распределения памяти прямо в отладчике, никто не мешает вам сделать это прямо в коде программы. Для этого добавьте в программу строку следующего вида:

Альтернативный вариант заключается в использовании функции _CrtSetBreakAlloc, которая делает то же самое:

Сравнение состояний памяти

Другой способ обнаружения утечек памяти подразумевает использование "моментальных снимков" (snapshots) памяти в ключевых точках вашей программы. Специально для хранения таких "снимков" в CRT предусмотрена структура _CrtMemState:

Чтобы сделать "снимок" памяти в некоторый момент времени, передайте указатель на структуру _CrtMemState функции _CrtMemCheckpoint. Эта функция записывает в структуру информацию о текущем состоянии памяти:

Вы можете в любой момент вывести содержимое структуры _CrtMemState, передав указатель на неё функции _CrtMemDumpStatistics:

Эта функция выдаёт отчёт обо всех выделенных блоках, который выглядит примерно так:

Чтобы определить, не было ли утечек памяти на каком-то участке вашей программы, вы можете сделать "снимки" памяти до и после этого участка, а затем вызвать _CrtMemDifference, чтобы сравнить два состояния:

Как и подразумевает её название, функция _CrtMemDifference сравнивает два состояния памяти (первые два параметра) и записывает разницу в третий параметр. Таким образом, размещение _CrtMemCheckpoint в начале и в конце вашей программы с последующим использованием _CrtMemDifference для сравнения состояний даёт вам ещё один метод контроля утечек памяти. Если утечка обнаружена, вы можете разбивать программу на части и искать, где она произошла, используя стратегию двоичного поиска.

Работаю под Visual Studio. Как узнать, есть ли в программе утечка памяти или нет?

2 ответа 2

Возможно обнаружение утечек памяти с помощью отладчика и отладочных функций кучи библиотеки CRT (библиотеки времени выполнения). Включаются они так:

Важно, что инструкции include / define следуют в таком порядке.

Включение заголовочного файла сопоставляет функции malloc и free с их отладочными версиями: _malloc_dbg и free . Инструкция define позволит сделать дамп утечки памяти более подробным (вообще говоря, она сопоставляет базовые версии функций кучи CRT соответствующим отладочным версиям).

Далее помещаем вызов _CrtDumpMemoryLeaks перед точкой выхода приложения для отображения отчета об утечке памяти перед завершением работы приложения:

Если точек выхода несколько, нет нужды писать вызов этой функции повсеместно. Достаточно вызвать в начале работы приложения функцию _CrtSetDbgFlag , что приведет к автоматическому вызову функции _CrtDumpMemoryLeaks в каждой точке выхода. Для этого надо установить значения двух битовых полей:

По умолчанию _CrtDumpMemoryLeaks выводит отчет об утечке памяти в область Отладка окна Вывод.

Далее смотрите полученные данные, там четко указывается тип блока, его расположение, размер утечки и еще некоторая информация. Блоки бывают разных типов (см. справку CRT).

Примечание: В некоторых случаях _CrtDumpMemoryLeaks может ошибочно диагностировать утечку памяти, но я не буду здесь расписывать данные ситуации, если потребуется или Вы не разберетесь самостоятельно — пишите комментарии;)

Утечки памяти являются наиболее заметно и жестких в обнаружении ошибок в приложениях C/C++. Memory leaks are among the most subtle and hard-to-detect bugs in C/C++ apps. Результат после сбоя при освобождении памяти, который ранее был выделен утечки памяти. Memory leaks result from the failure to correctly deallocate memory that was previously allocated. Небольшая утечка памяти, могут остаться незамеченными на первый, но со временем может привести к симптомы от низкой производительности до аварийного завершения приложения не хватает памяти. A small memory leak might not be noticed at first, but over time can cause symptoms ranging from poor performance to crashing when the app runs out of memory. Утечкой памяти приложения, которое использует всю доступную память может вызвать аварийное завершение работы других приложений, создание сомнения, какое приложение отвечает. A leaking app that uses up all available memory can cause other apps to crash, creating confusion as to which app is responsible. Даже взгляд утечка памяти могут свидетельствовать о других проблемах, которые должны быть исправлены. Even harmless memory leaks might indicate other problems that should be corrected.

Visual Studio Visual Studio Отладчика и библиотеки времени выполнения C (CRT) может помочь обнаружить и выявить утечки памяти. The Visual Studio Visual Studio debugger and C Run-time Library (CRT) can help you detect and identify memory leaks.

Включение обнаружения утечек памяти Enable memory leak detection

Основным средством для обнаружения утечек памяти является отладчик C/C++ и библиотека времени выполнения C (CRT) отладочные функции кучи. The primary tools for detecting memory leaks are the C/C++ debugger and the C Run-time Library (CRT) debug heap functions.

Чтобы включить все отладочные функции кучи, включите следующие инструкции в программе C++, в следующем порядке: To enable all the debug heap functions, include the following statements in your C++ program, in the following order:

Оператор #define сопоставляет базовые версии функций кучи CRT соответствующим отладочным версиям. The #define statement maps a base version of the CRT heap functions to the corresponding debug version. Если опустить #define инструкции, что дамп утечки памяти будет меньший. If you leave out the #define statement, the memory leak dump will be less detailed.

Включая crtdbg.h сопоставляет malloc и free функций с их отладочными версиями _malloc_dbg и _free_dbg, которые отслеживают памяти Выделение и освобождение. Including crtdbg.h maps the malloc and free functions to their debug versions, _malloc_dbg and _free_dbg, which track memory allocation and deallocation. Это сопоставление используется только в отладочных построениях, в которых определен _DEBUG . This mapping occurs only in debug builds, which have _DEBUG . В окончательных построениях используются первоначальные функции malloc и free . Release builds use the ordinary malloc and free functions.

После включения отладочные функции кучи с помощью предыдущие инструкции, поместите вызов _CrtDumpMemoryLeaks перед точкой выхода приложения для отображения отчета об утечке памяти, при выходе из приложения. After you’ve enabled the debug heap functions by using the preceding statements, place a call to _CrtDumpMemoryLeaks before an app exit point to display a memory-leak report when the app exits.

Читайте также:  Из двух простых высказываний постройте сложное высказывание

Если приложение имеет несколько завершает работу, не требуется вручную размещать _CrtDumpMemoryLeaks в каждой точке выхода. If your app has several exits, you don’t need to manually place _CrtDumpMemoryLeaks at every exit point. Чтобы привести к автоматическому вызову функции _CrtDumpMemoryLeaks в каждой точке выхода, поместите вызов _CrtSetDbgFlag в начале приложения с помощью показанных здесь битовых поля: To cause an automatic call to _CrtDumpMemoryLeaks at each exit point, place a call to _CrtSetDbgFlag at the beginning of your app with the bit fields shown here:

По умолчанию _CrtDumpMemoryLeaks выводит отчет об утечке памяти в область Отладка окна Вывод . By default, _CrtDumpMemoryLeaks outputs the memory-leak report to the Debug pane of the Output window. Если используется библиотека, она может переустановить вывод в другое расположение. If you use a library, the library might reset the output to another location.

Можно использовать _CrtSetReportMode для перенаправления отчета в другое расположение или обратно в вывода окна, как показано ниже: You can use _CrtSetReportMode to redirect the report to another location, or back to the Output window as shown here:

Интерпретация отчета об утечке памяти Interpret the memory-leak report

Если ваше приложение не определяет _CRTDBG_MAP_ALLOC , _CrtDumpMemoryLeaks отображает отчет об утечке памяти, который выглядит следующим образом: If your app doesn’t define _CRTDBG_MAP_ALLOC , _CrtDumpMemoryLeaks displays a memory-leak report that looks like:

Если ваше приложение определяет _CRTDBG_MAP_ALLOC , отчет об утечке памяти выглядит как: If your app defines _CRTDBG_MAP_ALLOC , the memory-leak report looks like:

Во втором отчете показано имя файла и номер строки, где сначала выделяется утечки памяти. The second report shows the filename and line number where the leaked memory is first allocated.

Ли вы определить _CRTDBG_MAP_ALLOC , в отчете об утечке памяти: Whether or not you define _CRTDBG_MAP_ALLOC , the memory-leak report displays:

  • Номер выделения памяти, который является 18 в примере The memory allocation number, which is 18 in the example
  • Тип блока, normal в примере. The block type, normal in the example.
  • Расположение памяти в шестнадцатеричном формате, 0x00780E80 в примере. The hexadecimal memory location, 0x00780E80 in the example.
  • Размер блока, 64 bytes в примере. The size of the block, 64 bytes in the example.
  • Первые 16 байт данных в блоке, в шестнадцатеричном формате. The first 16 bytes of data in the block, in hexadecimal form.

Типы блоков памяти являются обычный, клиента, или CRT. Memory block types are normal, client, or CRT. Обычный блок — это обыкновенная память, выделенная программой. A normal block is ordinary memory allocated by your program. Клиентский блок — особый тип блока памяти, используемой программами MFC для объектов, для которых требуется деструктор. A client block is a special type of memory block used by MFC programs for objects that require a destructor. Оператор new в MFC создает либо обычный, либо клиентский блок, в соответствии с создаваемым объектом. The MFC new operator creates either a normal block or a client block, as appropriate for the object being created.

Блок CRT — это блок памяти, выделенной библиотекой CRT для внутреннего использования. A CRT block is allocated by the CRT library for its own use. Освобождение этих блоков производится библиотекой CRT, поэтому блоки CRT не будет отображаться в отчете об утечке памяти, если существуют серьезные проблемы с библиотекой CRT. The CRT library handles the deallocation for these blocks, so CRT blocks won’t appear in the memory-leak report unless there are serious problems with the CRT library.

Существуют два других типа блоков памяти, которые никогда не отображаются в отчетах об утечке памяти. There are two other types of memory blocks that never appear in memory-leak reports. Объект свободных блоков памяти, которая была освобождена, поэтому по определению не утечки. A free block is memory that has been released, so by definition isn’t leaked. Пропускаемый блок — это память, вы специально помеченная для исключения из отчета об утечке памяти. An ignore block is memory that you’ve explicitly marked to exclude from the memory-leak report.

Выше методы определения утечки памяти для памяти, выделенной с помощью стандартных CRT malloc функции. The preceding techniques identify memory leaks for memory allocated using the standard CRT malloc function. Если программа выделяет память с помощью C++ new оператор, однако вы можете увидеть только имя файла и номер строки, где operator new вызовы _malloc_dbg в отчете об утечке памяти. If your program allocates memory using the C++ new operator, however, you may only see the filename and line number where operator new calls _malloc_dbg in the memory-leak report. Чтобы создать более отчет об утечке памяти, можно написать макрос следующим сообщить о строке, внесенные выделение: To create a more useful memory-leak report, you can write a macro like the following to report the line that made the allocation:

Теперь вы можете заменить new оператора с помощью DBG_NEW макрос в коде. Now you can replace the new operator by using the DBG_NEW macro in your code. В отладочных сборках DBG_NEW используется перегруженная версия глобального operator new , принимает дополнительные параметры для типа блока, файла и номер строки. In debug builds, DBG_NEW uses an overload of global operator new that takes additional parameters for the block type, file, and line number. Перегрузка new вызовы _malloc_dbg для записи дополнительных сведений. The overload of new calls _malloc_dbg to record the extra information. Отчеты об утечке памяти Показать имя файла и номер строки, где были выделены потерянные объекты. The memory-leak reports show the filename and line number where the leaked objects were allocated. Сборки выпуска, по-прежнему используют значение по умолчанию new . Release builds still use the default new . Ниже приведен пример этого метода: Here’s an example of the technique:

При выполнении этого кода в Visual Studio отладчика, вызов _CrtDumpMemoryLeaks создает отчет в вывода окно, которое выглядит так: When you run this code in the Visual Studio debugger, the call to _CrtDumpMemoryLeaks generates a report in the Output window that looks similar to:

Эти выходные данные отчетов, что утечка выделение было предназначено в строке 20 debug_new.cpp. This output reports that the leaked allocation was on line 20 of debug_new.cpp.

Мы не рекомендуем создать макрос препроцессора с именем new , или другие ключевое слово языка. We don’t recommend you create a preprocessor macro named new , or any other language keyword.

Установите точки останова для номера выделения памяти Set breakpoints on a memory allocation number

Номер выделения памяти сообщает, когда был выделен утекающий блок памяти. The memory allocation number tells you when a leaked memory block was allocated. Блок с номером выделения памяти 18 — например, — 18-й блок памяти, выделенной во время выполнения приложения. A block with a memory allocation number of 18, for example, is the 18th block of memory allocated during the run of the app. В отчете CRT учитываются все выделения блоков памяти во время выполнения, включая выделения, произведенные библиотекой CRT и другие библиотеки, например MFC. The CRT report counts all memory-block allocations during the run, including allocations by the CRT library and other libraries such as MFC. Таким образом эта память номер выделения блока 18, вероятно, станет 18-й блок памяти, выделенным вашим кодов. Therefore, memory allocation block number 18 probably isn’t the 18th memory block allocated by your code.

Читайте также:  Xcom 2 war of the chosen дополнения

Номер выделения можно использовать для того, чтобы задать точку останова в том месте, где выделяется память. You can use the allocation number to set a breakpoint on the memory allocation.

Установка точки останова для выделения памяти с помощью окна контрольных значений: To set a memory-allocation breakpoint using the Watch window:

Установите точку останова недалеко от начала приложения и начните отладку. Set a breakpoint near the start of your app, and start debugging.

Когда приложение приостанавливается в точке останова, откройте Watch окно, выбрав Отладка > Windows > Контрольные значения 1 (или Контрольные значения 2, Контрольное значение 3, или Контрольные значения 4). When the app pauses at the breakpoint, open a Watch window by selecting Debug > Windows > Watch 1 (or Watch 2, Watch 3, or Watch 4).

В Watch введите _crtBreakAlloc в имя столбца. In the Watch window, type _crtBreakAlloc in the Name column.

Если используется многопоточная версия DLL библиотеки CRT (параметр/MD), добавьте контекстный оператор: <,,ucrtbased.dll>_crtBreakAlloc If you’re using the multithreaded DLL version of the CRT library (the /MD option), add the context operator: <,,ucrtbased.dll>_crtBreakAlloc

Нажмите клавишу ВВОД. Press Enter.

Отладчик выполнит оценку вызова и поместит результат в столбец Значение . The debugger evaluates the call and places the result in the Value column. Это значение будет равно –1, если в местах выделения памяти не задано ни одной точки останова. This value will be -1 if you have not set any breakpoints on memory allocations.

В значение столбца, замените значение номером выделения памяти, где требуется останов отладчика. In the Value column, replace the value with the allocation number of the memory allocation where you want the debugger to break.

После выбора точки останова для номера выделения памяти, продолжите отладку. After you set a breakpoint on a memory-allocation number, continue to debug. Убедитесь в том, что для запуска под тем же условиям, поэтому номер выделения памяти не изменяется. Make sure to run under the same conditions, so the memory-allocation number doesn’t change. Когда выполнение программы будет приостановлено на заданном выделении памяти, используйте стек вызовов окно и других окон отладчика определите условия, при которых была выделена память. When your program breaks at the specified memory allocation, use the Call Stack window and other debugger windows to determine the conditions under which the memory was allocated. Затем можно продолжить выполнение, чтобы посмотреть, что происходит на объект и определить, почему он не освобождается неправильно. Then, you can continue execution to observe what happens to the object and determine why it isn’t correctly deallocated.

Иногда может быть полезно задать точку останова по данным на самом объекте. Setting a data breakpoint on the object might also be helpful. Для получения дополнительной информации см. раздел Использование точек останова. For more information, see Using breakpoints.

Точки останова для выделения памяти можно также задать в коде. You can also set memory-allocation breakpoints in code. Можно установить следующие значения: You can set:

Сравнение состояний памяти Compare memory states

Другая технология для обнаружения утечек памяти включает получение "снимков" состояния памяти приложения в ключевых точках. Another technique for locating memory leaks involves taking snapshots of the application’s memory state at key points. Чтобы получить снимок состояния памяти в заданной точке приложения, создайте _CrtMemState структурировать и передать его в _CrtMemCheckpoint функции. To take a snapshot of the memory state at a given point in your application, create a _CrtMemState structure and pass it to the _CrtMemCheckpoint function.

_CrtMemCheckpoint Функция поместит в структуру снимок текущего состояния памяти. The _CrtMemCheckpoint function fills in the structure with a snapshot of the current memory state.

Чтобы вывести содержимое _CrtMemState структуры, передайте ее _ CrtMemDumpStatistics функции: To output the contents of a _CrtMemState structure, pass the structure to the _ CrtMemDumpStatistics function:

_ CrtMemDumpStatistics Выводит дамп состояния памяти, который выглядит следующим образом: _ CrtMemDumpStatistics outputs a dump of memory state that looks like:

Чтобы определить, произошла ли утечка памяти на отрезке кода, можно сделать снимок состояния памяти перед ним и после него, а затем сравнить оба состояния с помощью функции _ CrtMemDifference : To determine whether a memory leak has occurred in a section of code, you can take snapshots of the memory state before and after the section, and then use _ CrtMemDifference to compare the two states:

_CrtMemDifference Сравнивает состояния памяти s1 и s2 и возвращает результат в ( s3 ) является различие между s1 и s2 . _CrtMemDifference compares the memory states s1 and s2 and returns a result in ( s3 ) that is the difference between s1 and s2 .

Еще один способ поиска утечек памяти заключается в размещении _CrtMemCheckpoint вызовы в начале и конце приложения, затем с помощью _CrtMemDifference сравнить результаты. One technique for finding memory leaks begins by placing _CrtMemCheckpoint calls at the beginning and end of your app, then using _CrtMemDifference to compare the results. Если _CrtMemDifference показывает утечку памяти, можно добавить несколько _CrtMemCheckpoint вызовы, чтобы разделить программу с помощью двоичного поиска, пока вы определили, что источник утечки. If _CrtMemDifference shows a memory leak, you can add more _CrtMemCheckpoint calls to divide your program using a binary search, until you’ve isolated the source of the leak.

Ложные срабатывания False positives

_CrtDumpMemoryLeaks можно дать ошибочно диагностировать утечку памяти, если библиотеку внутренние выделения как обычных блоков вместо блоки CRT или клиентские блоки. _CrtDumpMemoryLeaks can give false indications of memory leaks if a library marks internal allocations as normal blocks instead of CRT blocks or client blocks. В таком случае функция _CrtDumpMemoryLeaks не может различать пользовательские выделения и внутренние выделения библиотеки. In that case, _CrtDumpMemoryLeaks is unable to tell the difference between user allocations and internal library allocations. Если глобальные деструкторы для выделений библиотеки выполняются после точки вызова функции _CrtDumpMemoryLeaks , каждое внутреннее выделение библиотеки принимается за утечку памяти. If the global destructors for the library allocations run after the point where you call _CrtDumpMemoryLeaks , every internal library allocation is reported as a memory leak. Версии библиотеки стандартных шаблонов раньше, чем Visual Studio .NET может привести к _CrtDumpMemoryLeaks сообщить о таких ложных положительных результатов. Versions of the Standard Template Library earlier than Visual Studio .NET may cause _CrtDumpMemoryLeaks to report such false positives.

Ссылка на основную публикацию
Adblock
detector