Принцип Работы Детекторов Утечки Памяти


Как на самом деле работают детекторы утечки памяти? Каковы основные понятия в целом? Можно взять C++ в качестве языка, чтобы объяснить это.

3 51

3 ответа:

есть несколько различных способов работы детекторов утечки. Вы можете заменить реализацию malloc и free с теми, которые могут отслеживать дополнительную информацию во время распределения и не связаны с производительностью. Это похоже на то, как dmalloc строительство. В общем, любой адрес, который mallocЭД, но не free'D это слил.

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

на практике вам, вероятно, понадобится больше, чем просто номер одной строки, а скорее трассировка стека для потерянных распределений.

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

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

C++ делает вещи немного сложнее для обоих типов детекторов утечки, потому что он добавляет new и delete операторы. Технически new может быть совершенно другой источник памяти, чем malloc. Однако на практике многие реальные реализации C++ просто используют malloc для реализации new или есть возможность использовать malloc вместо альтернативного подход.

также языки более высокого уровня, такие как C++, как правило, имеют альтернативные способы выделения памяти более высокого уровня, такие как std::vector или std::list. Основной детектор утечки сообщал бы о потенциально многих распределениях, сделанных режимами более высокого уровня отдельно. Это гораздо менее полезно, чем сказать, что весь контейнер был потерян.

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

в основном он отслеживает время жизни всех значений (куча и стек), а также их размеры в соответствии с их типами, определенными языком. Это позволяет CheckPointer находить не только утечки, но и доступы вне массива, даже для массивов в стеке, которые valgrind не будет делать.

в частности, он анализирует исходный код, чтобы найти все указатель использует. (Это довольно сложная задача просто сам по себе).

он отслеживает метаданные указателя для каждого указателя, состоящего из

  • ссылка на метаданные объекта для выделенного кучей объекта или глобальной или локальной переменной orfunction, на которую указывает указатель и
  • диапазон адресов (sub) объекта объекта, к которому в данный момент может обращаться указатель. Это может быть меньше, чем диапазон адресов весь объект; например, если вы берете адрес члена структуры, то инструментированный исходный код будет разрешать доступ к этому элементу только при использовании результирующего указателя.

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

  • диапазон адресов объекта, к которому можно безопасно получить доступ, и
  • для каждого указателя, хранящегося в куче объект или переменная, ссылка на метаданные указателя для этого указателя.

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

Это помечено C и C++, и никакая операционная система не упоминается. Этот ответ для Windows.

C

Windows имеет понятие виртуальной памяти. Любая память, которую может получить процесс, является виртуальной памятью. Это делается через VirtualAlloc () [MSDN]. Вы можете представить себе детектор утечки, чтобы поставить точку останова на этой функции, и всякий раз, когда он вызывается, он получает стек вызовов и сохраняет его где-то. Тогда он может сделать подобное для VirtualFree () [MSDN].

разница может быть идентифицирована и показана вместе с сохраненными стеками вызовов.

C++

C++ имеет другую концепцию: он берет большие блоки 64kb, которые он получает от VirtualAlloc() и разбивает его на более мелкие части, называемые кучей. Менеджер кучи C++ поставляется от Microsoft и предлагает новые методы HeapAlloc () [MSDN] и HeapFree () [MSDN].

тогда, вы могли бы сделать то же, что и раньше, но на самом деле, эта функция уже встроенная. Microsoft GFlags [MSDN] инструмент может включить отслеживание:

Screenshot: GFlags enabled for Notepad

в этом случае он сохранит до 50 Мб информации о стеке вызовов для вызовов диспетчера кучи C++.

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

общее понятие

Как вы можете видеть, общая концепция заключается в отслеживании распределения и освобождения, сравнить их и показать стеки вызовов разницы.