Как вы обнаруживаете / избегаете утечек памяти в вашем (неуправляемом) коде?

Каковы наилучшие методы обнаружения утечек памяти в неуправляемом коде C / C++? И рекомендаций по кодированию, которых следует избегать? (Как будто это так просто;)

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

Я знаю, что это не лучший способ и есть несколько уловок. (Например, если вы освобождаете память, которая была выделена вызовом API платформы, ваш счетчик выделения не будет точно соответствовать вашему счетчику освобождения. Конечно, тогда мы увеличили счетчик при вызове вызовов API, которые выделяли память.)

Я жду вашего опыта, предложений и, возможно, некоторых ссылок на инструменты, которые упростят это.

вы ищите valgrind (для linux) или deleaker (для windows), также смотрите визуальный детектор утечек ...

John Smith 23.02.2012 00:00

для поиска утечек памяти проверьте здесь: theunixshell.blogspot.com/2013/11/…

Vijay 29.11.2013 13:01

Что касается предотвращения утечек, в следующем посте есть несколько советов: http://stackoverflow.com/questions/27492/c-memory-management

tonylo 06.09.2008 13:16

Я использовал это с Visual Studio для обнаружения утечки памяти. codeproject.com/KB/applications/visualleakdetector.aspx

tiboo 12.11.2010 06:16

Я задал этот вопрос здесь: http://stackoverflow.com/questions/25730/what-is-the-best-fr ee-memory-Leak-Detec tor-for-a-cc-program‌ -and-its-plug-in-dll‌ S и имел большой успех с Визуальный детектор утечки.

Jim Buck 06.09.2008 14:57
saunalahti.fi/~tarmpika/diagnostic I had tried so many memory leak detectors that it's difficult to count them all. Some of them crashed, some of them produced invalid results, some of them simply did not help. Eventually I've made my own leak detector, but invested so much effort into it - so made it non-free for timebeing. Managed / native / 32 & 64-bit architectures supported.
TarmoPikaro 09.02.2016 20:36

Веб-страница упала, но теперь я решил опубликовать исходный код своего инструмента - вот он: sourceforge.net/projects/diagnostic

TarmoPikaro 22.09.2016 23:30

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

CashCow 24.11.2016 15:04
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
125
8
161 341
29

Ответы 29

Сам никогда не использовал, но мои друзья C говорят мне Очистить.

Существуют различные замещающие библиотеки "malloc", которые позволят вам вызвать функцию в конце, и она расскажет вам обо всей неиспользованной памяти и, во многих случаях, о том, кто ее создал (или обновил) в первую очередь. .

Если ваш код C / C++ переносится на * nix, лучше Валгринд мало что может.

Valgrind теперь также работает с OS X, поэтому Linux - не единственный вариант.

Michael Anderson 12.10.2010 07:01

Valgrind для Linux (и OS X). Если использовать виндовс - делекер - лучше всего!

John Smith 12.12.2011 22:12

@JordiBunster: Отлично! Но на основе времени выполнения. С большой кодовой базой (написано на C в случае необходимости) вы в основном будете тестировать свою программу на то, как она была спроектирована. Злоумышленник может потратить несколько тысяч часов на чтение кода, чтобы найти эксплойт утечки памяти. Я ожидал появления автоматизированного инструмента для анализа исходного кода, подобного тому, который существует для JavaScript.

user2284570 02.10.2015 16:50

Работая в операционной системе сотовых телефонов Motorola, мы взяли библиотеку распределения памяти, чтобы наблюдать за всем распределением памяти. Помогло найти много проблем с выделением памяти. Поскольку профилактика лучше лечения, я бы рекомендовал использовать инструмент статического анализа, такой как Klockwork или PC-Lint.

Шина - это новая замена ворса.

Mark Kegel 12.10.2008 16:43

@ user14788: Продукт Gimpel PC-Lint намного современнее старого Unix lint. В нем есть много проверок, специфичных для C++, чего нет в afaik splint. См. Ссылку в ответе (который я переименовал с Lint в PC-Lint).

Dan 12.10.2010 06:57

Вы подсчитываете выделение и освобождение, интерполируя свои собственные функции системных вызовов, которые записывают вызовы, а затем передают вызов реальной функции?

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

Взгляните на страницу руководства для ld.so. Или ld.so.1 в некоторых системах.

Также сделайте Google LD_PRELOAD, и вы найдете несколько интересных статей, объясняющих эту технику, на www.itworld.com.

Как разработчик C++ вот несколько простых рекомендаций:

  1. Используйте указатели только в случае крайней необходимости
  2. Если вам нужен указатель, дважды проверьте, возможен ли SmartPointer
  3. Используйте шаблон GRASP Создатель.

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

Visual Leak Detectore перемещен на новый сайт vld.codeplex.com

KindDragon 05.04.2011 01:19

VLD - ДЕЙСТВИТЕЛЬНО хороший течеискатель - я полностью рекомендую его всем, кто использует VC++.

Javid 09.09.2016 20:55

+1 за пункт №1. Это абсолютно фундаментальная вещь. К сожалению, мне кажется, что некоторые из крупнейших библиотек "C++" склонны избегать выделения стека и / или RAII в пользу Pointers Everywhere, часто без видимой причины. Таким образом, они становятся «C с классами», а не настоящим C++.

underscore_d 17.01.2017 04:11

Microsoft VC++ в режиме отладки показывает утечки памяти, но не показывает, где находятся ваши утечки.

Если вы используете C++, вы всегда можете избежать использования new явно: у вас есть vector, string, auto_ptr (до C++ 11; заменен на unique_ptr в C++ 11), unique_ptr (C++ 11) и shared_ptr (C++ 11) в вашем арсенале.

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

и не забывайте правило 3 или 5, тогда

Humam Helfawi 22.06.2016 10:43

Если вы используете Visual Studio, возможно, стоит взглянуть на Проверка границ. Это не бесплатно, но очень помогло в поиске утечек в моем коде. Это происходит не только с утечками памяти, но и с утечками ресурсов GDI, ошибками использования WinAPI и прочим. Он даже покажет вам, где была инициализирована утечка памяти, что значительно упростит отслеживание утечки.

Если вы используете MS VC++, я настоятельно рекомендую этот бесплатный инструмент из codeproject: поисковик, автор - Йохен Кальмбах.

Вы просто добавляете класс в свой проект и вызываете

InitAllocCheck(ACOutput_XML)
DeInitAllocCheck()

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

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

PurifyPlus от Rational (ныне принадлежащий IBM) иллюстрирует утечки аналогичным образом, но я считаю, что инструмент Leakfinder действительно проще в использовании, причем бонус в том, что он не стоит несколько тысяч долларов!

Я проверил утечку, и он выглядит нормально, но к вашему сведению, он не будет работать как есть для x64, потому что он содержит встроенную сборку.

Zach 12.02.2009 17:45

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

Отслеживание запросов на выделение кучи - в частности, раздел об уникальных номерах запросов на выделение

_CrtSetDbgFlag

_CrtSetBreakAlloc

Конечно, если вы не используете DevStudio, это не принесет особой пользы.

По крайней мере, для MS VC++ библиотека C Runtime имеет несколько функций, которые я считал полезными в прошлом. Обратитесь к справке MSDN о функциях _Crt*.

В C++: используйте RAII. Умные указатели вроде std::unique_ptr, std::shared_ptr, std::weak_ptr - ваши друзья.

а std: vector - отличная замена, когда массивы (буферы) освобождаются в той же функции, в которой они выделяются.

KJAWolf 30.09.2008 17:47

По крайней мере, std :: auto_ptr и boost :: shared_ptr все еще подвержены утечкам.

Jasper Bekkers 23.12.2008 02:55

Только если вы используете их неправильно, хотя я должен признать, что для std :: auto_ptr неправильно использовать его довольно просто.

Leon Timmermans 08.01.2009 17:23

Хотя это хороший совет для стандартов кодирования, он не дает ответа на вопрос. Даже использование shared_ptr может привести к утечкам с круговыми зависимостями. И у вас могут быть «утечки» с неограниченными стратегиями кэширования, которые применимы даже к языкам со сборкой мусора.

CashCow 24.11.2016 15:03

@CashCow: вы правы. Хотя я еще не видел этого на практике, вероятно, потому, что я использую их экономно. Процитируем ответ ниже: «Используйте указатели только в случае крайней необходимости».

Leon Timmermans 24.11.2016 18:42

Valgrind - хороший вариант для Linux. В MacOS X вы можете включить библиотеку MallocDebug, в которой есть несколько опций для отладки проблем с распределением памяти (см. Справочную страницу malloc, в разделе «ОКРУЖЕНИЕ» есть соответствующие детали). OS X SDK также включает инструмент под названием MallocDebug (обычно устанавливается в / Developer / Applications / Performance Tools /), который может помочь вам отслеживать использование и утечки.

Я думаю, что на этот вопрос нет простого ответа. Как вы действительно можете подойти к этому решению, зависит от ваших требований. Вам нужно кроссплатформенное решение? Вы используете new / delete или malloc / free (или оба)? Вы действительно ищете только «утечки» или вам нужна лучшая защита, например, обнаружение переполнения (или опустошения) буфера?

Если вы работаете на стороне Windows, библиотеки времени выполнения отладки MS имеют некоторые базовые функции обнаружения отладки, и, как уже указывал другой, есть несколько оболочек, которые могут быть включены в ваш источник, чтобы помочь с обнаружением утечек. Очевидно, что поиск пакета, который может работать как с new / delete, так и с malloc / free, дает вам больше гибкости.

Я недостаточно знаю о стороне Unix, чтобы оказать помощь, хотя, опять же, другие знают.

Но помимо обнаружения утечек существует понятие обнаружения повреждения памяти через переполнение (или опустошение) буфера. Я думаю, что этот тип отладки сложнее, чем простое обнаружение утечек. Этот тип системы также усложняется, если вы работаете с объектами C++, поскольку полиморфные классы могут быть удалены различными способами, что затрудняет определение истинного базового указателя, который удаляется. Я не знаю хорошей «бесплатной» системы, которая бы обеспечивала достойную защиту от переполнения. мы написали систему (кроссплатформенную) и обнаружили, что это довольно сложно.

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

  1. Вы можете найти это полезным.

  2. Хотя это немного круфно, я не позволяю этому смущать меня.

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

Есть вещи, с которыми вы должны быть осторожны при его использовании: не делайте ничего, что должно опираться на new в базовом коде, остерегайтесь предупреждений о случаях, которые он может пропустить в верхней части leakcheck.cpp, поймите, что если вы включите (и исправьте любые проблемы) код, который выполняет дампы изображений, вы можете создать огромный файл.

Дизайн предназначен для того, чтобы вы могли включать и выключать средство проверки без перекомпиляции всего, что включает его заголовок. Включите файл leakcheck.h, где вы хотите отслеживать проверку и один раз перестроить. После этого скомпилируйте leakcheck.cpp с LEAKCHECK #define'd или без него, а затем повторно подключите его, чтобы включить и выключить. Включение unleakcheck.h отключит его локально в файле. Предусмотрены два макроса: CLEARALLOCINFO () позволит избежать неправильного сообщения одного и того же файла и строки, когда вы просматриваете выделенный код, который не включал leakcheck.h. ALLOCFENCE () просто отбрасывает строку в сгенерированном отчете без выделения памяти.

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

Вы можете найти его здесь: http://www.cse.ucsd.edu/~tkammeye/leakcheck.html

Обнаружить:

Отладка CRT

Избегать:

Умные указатели, Boehm GC

Если вы используете Visual Studio, Microsoft предоставляет несколько полезных функций для обнаружения и отладки утечек памяти.

Я бы начал с этой статьи: https://msdn.microsoft.com/en-us/library/x98tx3cf(v=vs.140).aspx

Вот краткое изложение этих статей. Сначала включите эти заголовки:

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

Затем вам нужно вызвать это при выходе из вашей программы:

_CrtDumpMemoryLeaks();

В качестве альтернативы, если ваша программа не выходит каждый раз в одном и том же месте, вы можете вызвать это в начале своей программы:

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

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

Эта стратегия работает для большинства программ. Однако в некоторых случаях это становится трудным или невозможным. Использование сторонних библиотек, которые выполняют некоторую инициализацию при запуске, может вызвать появление других объектов в дампе памяти и затруднить отслеживание ваших утечек. Кроме того, если какой-либо из ваших классов имеет члены с тем же именем, что и любая из подпрограмм распределения памяти (например, malloc), макросы отладки CRT вызовут проблемы.

Существуют и другие методы, описанные в упомянутой выше ссылке MSDN, которые также можно использовать.

Замечание об этом методе: похоже, что он работает, только если вы используете чистый C с malloc и free. Подробный отчет, который включает номера строк, не создается, если вы используете C++ new и delete.

Zach 12.02.2009 17:48

@Zach: на самом деле вы тоже можете заставить это работать (в любом случае, для любого кода, который вы действительно компилируете) - см. Принятый ответ в social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/…

Roman Starkov 09.02.2010 04:43

Будет ли это работать и в режиме выпуска?

J V 21.07.2015 09:14

@ user3152463 Нет. По документации будет работать только для отладочной сборки: msdn.microsoft.com/en-us/library/e5ewb1h3(v=vs.71).aspx

Dusty Campbell 22.07.2015 08:50

Эта строка неверна: #define CRTDBG_MAP_ALLOC Это должно быть: #define _CRTDBG_MAP_ALLOC

Fallso 22.06.2016 11:10

Если вы используете C++, вы можете создать класс, который его деструктор вызывает _CrtDumpMemoryLeaks, и создать его статический экземпляр. деструктор будет вызываться при выходе из приложения

David Haim 11.03.2017 13:28

Mmgr Пола Неттла - мой давний любимый инструмент. Вы включаете mmgr.h в свои исходные файлы, определяете TEST_MEMORY, и он доставляет текстовый файл, полный проблем с памятью, возникших во время запуска вашего приложения.

Для Linux: Попробуйте Google Perftools

Есть много инструментов, которые делают аналогичный подсчет распределения / свободного места, плюсы Goolge Perftools:

  • Довольно быстро (по сравнению с valgrind: очень быстро)
  • Поставляется с красивым графическим отображением результатов
  • Имеет другие полезные возможности: профилирование процессора, профилирование использования памяти ...

перейти к: github.com/gperftools/gperftools

Michael 17.06.2017 03:09

Общие правила кодирования:

  • Ресурсы должны быть освобождены на том же «уровне» (функция / класс / библиотека), где они размещены.
  • Если это невозможно, попробуйте использовать автоматическое освобождение (увеличить общий указатель ...)

Лучшая защита от утечек - это структура программы, которая сводит к минимуму использование malloc. Это не только хорошо с точки зрения программирования, но также повышает производительность и удобство обслуживания. Я не говорю об использовании других вещей вместо malloc, но с точки зрения повторного использования объектов и сохранения очень явных вкладок для всех передаваемых объектов, а не распределения волей-неволей, как это часто бывает в языках со сборщиками мусора как Java.

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

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

Очень полный и быстрый инструмент.

Memory Validator также предоставляет имя файла и номер строки для C#, который вызывает ваш собственный код. 64-разрядная версия находится в стадии бета-тестирования

Stephen Kellett 09.10.2010 20:48

Я удивлен, что никто не упомянул DebugDiag для ОС Windows. Работает и на релизных сборках, и даже на сайте заказчика. (Вам просто нужно сохранить PDB версии выпуска и настроить DebugDiag для использования общедоступного сервера символов Microsoft)

Ссылка больше не работает, попробуйте здесь для документации: support.microsoft.com/kb/2580960 и здесь, чтобы скачать: microsoft.com/en-us/download/details.aspx?id=26798

JPaget 19.09.2012 00:04

Хорошая замена malloc, calloc и reallloc - это rmdebug, она довольно проста в использовании. Это намного быстрее, чем valgrind, поэтому вы можете тщательно протестировать свой код. Конечно, у него есть свои недостатки: как только вы обнаружите утечку, вам, вероятно, все равно придется использовать valgrind, чтобы найти место ее появления, и вы можете тестировать только те маллоки, которые вы делаете напрямую. Если утечка библиотеки происходит из-за того, что вы ее неправильно используете, rmdebug ее не найдет.

http://www.hexco.de/rmdebug/

Visual Leak Detector - очень хороший инструмент, хотя он не поддерживает вызовы во время выполнения VC9 (например, MSVCR90D.DLL).

Этот инструмент действительно идеален! Это избавляет вас от необходимости использовать _CrtDumpMemoryLeaks (); и друзья, как описано в MSDN. Всего одно включение, и он все раскрывает! Работает даже в старых библиотеках C!

m_pGladiator 18.02.2010 13:43

Новая версия (для VS2013) находится здесь: vld.codeplex.com

Dženan 17.07.2014 20:04

Mtrace кажется стандартным встроенным для Linux. Шаги следующие:

  1. настроить переменную среды MALLOC_TRACE в bash
    MALLOC_TRACE = / tmp / mtrace.dat
    экспорт MALLOC_TRACE;
  2. Добавьте #include <mcheck.h> в начало вашего основного исходного файла
  3. Добавьте mtrace (); в начале main и muntrace (); внизу (перед оператором return)
  4. скомпилируйте свою программу с ключом -g для получения отладочной информации
  5. запустить вашу программу
  6. отображать информацию об утечке с помощью
    mtrace имя_вашего_программы /tmp/mtrace.dat
    (Мне сначала пришлось установить perl-скрипт mtrace в моей системе Fedora с yum установить glibc_utils  )

mtrace не очень полезен для C++

Erin 20.09.2016 01:35

Инструменты отладки памяти на вес золота, но с годами я обнаружил, что можно использовать две простые идеи, чтобы предотвратить кодирование большинства утечек памяти / ресурсов.

  1. Напишите код выпуска сразу после написания кода приобретения для ресурсов, которые вы хотите выделить. С помощью этого метода труднее «забыть» и в некотором смысле заставляет серьезно задуматься о жизненном цикле ресурсов, используемых заранее, а не как побочные.

  2. Используйте отдачу как можно реже. То, что выделено, по возможности следует освобождать только в одном месте. Условный путь между получением ресурса и выпуском должен быть максимально простым и очевидным.

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

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

Вот где на сцену выходит сэмплинг Монте-Карло. Прочтите статью в блоге Раймонда Чена, «Способ бедняков определять утечки памяти», а затем проверить мою реализацию (предполагается, что Linux, протестирован только на x86 и x86-64)

http://github.com/tialaramex/leakdice/tree/master

Большинство профилировщиков памяти замедляют работу моего большого сложного приложения Windows до такой степени, что результаты становятся бесполезными. Есть один инструмент, который хорошо работает для поиска утечек в моем приложении: UMDH - http://msdn.microsoft.com/en-us/library/ff560206%28VS.85%29.aspx

Я не понимаю, почему замедление делает результаты бесполезными. Несомненно, утечка памяти происходит независимо от скорости работы программы. Смысл этих инструментов - найти утечки, так в чем же проблема? Неужели он работал так медленно, что вы физически не могли заставить его покрыть все пути кода, чтобы профилировать их?

underscore_d 17.01.2017 04:08

Другие вопросы по теме