Подтвердить что ты не робот

Принцип работы детектора утечки памяти

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

Ответ 2

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

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

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

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

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

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

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

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

Ответ 3

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

С

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

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

С++

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

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

Screenshot: GFlags enabled for Notepad

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

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

Общая концепция

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