Я программист C ++ на платформе Windows. Я использую Visual Studio 2008.
Я обычно заканчиваю в коде с утечками памяти.
Обычно я проверяю код на наличие утечки памяти, но она громоздка и не всегда подходит.
Поскольку я не могу позволить себе платное средство обнаружения утечек памяти, я хотел, чтобы вы, ребята, предложили наилучшие возможные способы избежать утечек памяти.
- Я хочу знать, как программист может найти утечки памяти.
- Существует ли какой-либо стандарт или процедура, которой следует следовать, чтобы убедиться в отсутствии утечки памяти в программе?
c++
memory-leaks
Chris_vr
источник
источник
Ответы:
инструкции
Вещи, которые вам понадобятся
1
Понять основы оператора. Оператор C ++
new
выделяет кучу памяти.delete
Операторских освобождает память кучи. Для каждогоnew
вы должны использоватьdelete
так, чтобы вы освободили ту же память, что и выделенную:2
Перераспределять память, только если вы удалили. В приведенном ниже коде
str
получает новый адрес со вторым распределением. Первый адрес теряется безвозвратно, как и 30 байтов, на которые он указывал. Теперь их невозможно освободить, и у вас есть утечка памяти:3
Смотреть эти указатели назначений. Каждая динамическая переменная (выделенная память в куче) должна быть связана с указателем. Когда динамическая переменная отсоединяется от своего указателя (ей), ее становится невозможно стереть. Опять же, это приводит к утечке памяти:
4
Будьте осторожны с местными указателями. Указатель, который вы объявляете в функции, размещается в стеке, но динамическая переменная, на которую он указывает, размещается в куче. Если вы не удалите его, оно будет сохраняться после выхода из функции:
5
Обратите внимание на квадратные скобки после «удалить». Используйте
delete
само по себе, чтобы освободить один объект. Используйтеdelete []
с квадратными скобками, чтобы освободить массив кучи. Не делай что-то вроде этого:6
Если утечка еще разрешена - я обычно ищу ее с помощью deleteaker (проверьте это здесь: http://deleaker.com ).
источник
someFunction("some parameter")
я должен удалить"some parameter"
вsomeFunction
, после вызова функции, или они автоматически удаляются?Вы можете использовать некоторые методы в своем коде для обнаружения утечки памяти. Самый распространенный и самый простой способ обнаружить - определить макрос, скажем, DEBUG_NEW, и использовать его вместе с предопределенными макросами, такими как
__FILE__
и,__LINE__
чтобы обнаружить утечку памяти в вашем коде. Эти предопределенные макросы сообщают вам номер файла и номер строки утечки памяти.DEBUG_NEW - это просто MACRO, который обычно определяется как:
Так что, где бы вы ни использовали
new
, он также может отслеживать файл и номер строки, которые могут быть использованы для обнаружения утечки памяти в вашей программе.И
__FILE__
,__LINE__
которые предопределены макросы которые оценивают в имя файла и номер строки , соответственно , где вы их использовать!Прочитайте следующую статью, в которой очень красиво объясняется техника использования DEBUG_NEW с другими интересными макросами:
Кросс-платформенный детектор утечки памяти
Из Википедии ,
источник
#define
можетoperator new
привести к перегрузке и появлению ошибок компилятора. Даже если вам удастся преодолеть это, перегруженные функции не будут решены. Хотя техника хороша, иногда требуется много изменений кода.auto_ptr
не будет работать со стандартными контейнерами, такими какstd::vector
иstd::list
т. Д. См .: stackoverflow.com/questions/111478/…operator new
и какие версии вы используете?Существует несколько хорошо известных методов программирования, которые помогут вам свести к минимуму риск утечек памяти из первых рук:
new
иdelete
всегда попарно, и убедитесь, что код выделения / освобождения вызывается попарноvector<T> t
везде , где возможно, вместоT* t = new T[size]
источник
Valgrind http://valgrind.org/
и
GDB http://www.gnu.org/software/gdb/
источник
gflags
утилиту для включения трассировки стека в пользовательском режиме.UMDH
чтобы сделать несколько снимков памяти вашей программы. Сделайте снимок до того, как будет выделена память, и сделайте второй снимок после того момента, когда вы считаете, что в вашей программе произошла утечка памяти. Возможно, вы захотите добавить паузы или подсказки в вашу программу, чтобы дать вам возможность запуститьUMDH
и сделать снимки.UMDH
снова, на этот раз в своем режиме, который делает различие между двумя снимками. Затем он сгенерирует отчет, содержащий стеки вызовов о предполагаемых утечках памяти.gflags
настройки, когда закончите.UMDH
даст вам больше информации, чем куча отладки CRT, потому что она следит за распределением памяти по всему вашему процессу; он даже может сказать вам, протекают ли сторонние компоненты.источник
Запустить «Валгринд» можно:
1) Помогите определить утечки памяти - покажите, сколько у вас утечек памяти, и укажите на строки в коде, где была выделена утечка памяти.
2) Укажите неправильные попытки освободить память (например, неправильный вызов
delete
)Инструкция по применению "Valgrind"
1) Получить Valgrind здесь .
2) Скомпилируйте ваш код с
-g
флагом3) В вашей оболочке запустите:
Где «MyProg» ваша программа компилируется и
arg1
,arg2
аргументы вашей программы.4) Результатом является список звонков на
malloc
/new
которые не имели последующих звонков на бесплатное удаление.Например:
Сообщает вам, в какой строке
malloc
(что не было освобождено) был вызван.Как указано другими, убедитесь, что для каждого
new
/malloc
вызова у вас есть последующийdelete
/free
вызов.источник
Если вы используете gcc, есть gprof.
Кто-то использует инструменты, кто-то делает то, что вы делаете
Для меня: всякий раз, когда я создаю динамически размещенные объекты, я всегда помещаю код освобождения после, затем заполняю код между ними. Это будет нормально, если вы уверены, что в коде не будет исключений. В противном случае, я использую try-finally (я не часто использую C ++).
источник
В visual studio имеется встроенный детектор утечки памяти, который называется C Runtime Library. Когда ваша программа завершает работу после возврата основной функции, CRT проверит кучу отладки вашего приложения. если у вас есть какие-либо блоки, все еще выделенные в куче отладки, то у вас есть утечка памяти ..
Этот форум обсуждает несколько способов избежать утечки памяти в C / C ++.
источник
Найдите в своем коде вхождения
new
и убедитесь, что все они встречаются в конструкторе с соответствующим удалением в деструкторе. Убедитесь, что это единственная возможная операция в этом конструкторе. Простой способ сделать это - обернуть все указателиstd::auto_ptr
илиboost::scoped_ptr
(в зависимости от того, нужна ли вам семантика перемещения). Для всего будущего кода просто убедитесь, что каждый ресурс принадлежит объекту, который очищает ресурс в его деструкторе. Если вам нужна семантика перемещения, вы можете перейти на компилятор, который поддерживает ссылки на r-значения (я полагаю, VS2010) и создать конструкторы перемещения. Если вы не хотите этого делать, вы можете использовать различные хитрые приемы, связанные с добросовестным использованием swap, или попробовать библиотеку Boost.Move.источник
scope_ptr
s, и каждый инициализируется индивидуально, то все успешно построенные будут удалять свои указатели, а остальные все равно не будут держать указатели на выделенную память. Я приведу пример через несколько часов, когда вернусь домой с работы.Вы можете использовать инструмент Valgrind для обнаружения утечек памяти.
Также, чтобы найти утечку в конкретной функции, используйте exit (0) в конце функции, а затем запустите ее с Valgrind
источник
Обзор автоматических контроллеров утечки памяти
В этом ответе я сравниваю несколько различных средств проверки утечки памяти в простом, понятном примере утечки памяти.
Прежде всего, посмотрите на эту огромную таблицу в вики ASan, которая сравнивает все инструменты, известные человеку: https://github.com/google/sanitizers/wiki/AddressSanitizerComparisonOfMemoryTools/d06210f759fec97066888e5f27c7e722832b0924
Анализируемый пример будет:
main.c
GitHub вверх по течению .
Мы попытаемся увидеть, насколько четко различные инструменты указывают нам на утечки вызовов.
tcmalloc от gperftools от Google
https://github.com/gperftools/gperftools
Использование в Ubuntu 19.04:
Результат выполнения программы содержит анализ утечки памяти:
и вывод
google-pprof
содержит анализ использования кучи:Вывод указывает нам на две из трех утечек:
Я не уверен, почему третий не появился
В любом случае, когда обычно, когда что-то протекает, это случается много раз, и когда я использовал это в реальном проекте, я просто очень легко указывал на функцию утечки.
Как уже упоминалось в выходных данных, это приводит к значительному замедлению выполнения.
Дополнительная документация по адресу:
Смотрите также: Как использовать TCMalloc?
Проверено в Ubuntu 19.04, google-perftools 2.5-2.
Адрес Sanitizer (ASan) также от Google
https://github.com/google/sanitizers
Ранее упоминалось по адресу: Как найти утечку памяти в коде / проекте C ++? ТОДО против tcmalloc.
Это уже интегрировано в GCC, так что вы можете просто сделать:
и результаты выполнения:
который четко идентифицирует все утечки. Ницца!
ASan также может выполнять другие классные проверки, такие как запись за пределами поля: обнаружен разрыв стека
Протестировано в Ubuntu 19.04, GCC 8.3.0.
Valgrind
http://www.valgrind.org/
Ранее упоминалось по адресу: https://stackoverflow.com/a/37661630/895245
Использование:
Вывод:
Итак, еще раз, все утечки были обнаружены.
Смотрите также: Как мне использовать valgrind для поиска утечек памяти?
Протестировано в Ubuntu 19.04, valgrind 3.14.0.
источник
Visual Leak Detector (VLD) - это бесплатная, надежная система обнаружения утечек памяти с открытым исходным кодом для Visual C ++.
Если у вас есть только аварийные дампы, вы можете использовать команду Windbg
!heap -l
, она обнаружит пропущенные блоки кучи. Лучше откройте опцию gflags: «Создать базу данных трассировки стека в режиме пользователя», тогда вы увидите стек вызовов выделения памяти.источник
MTuner - это бесплатный мультиплатформенный инструмент для профилирования памяти, обнаружения и анализа утечек, поддерживающий компиляторы MSVC, GCC и Clang. Особенности включают в себя:
Пользователи могут профилировать любые программные платформы с кросс-компиляторами GCC или Clang. MTuner поставляется со встроенной поддержкой платформ Windows, PlayStation 4 и PlayStation 3.
источник
В Windows вы можете использовать CRT debug heap .
Да, не используйте ручное управление памятью (если вы когда-либо звоните
delete
илиdelete[]
вручную, то вы делаете это неправильно). Используйте RAII и умные указатели, ограничьте выделение кучи абсолютным минимумом (в большинстве случаев автоматических переменных будет достаточно).источник
Отвечая на вторую часть вашего вопроса,
Да, есть. И это одно из ключевых отличий между C и C ++.
В C ++ вы никогда не должны вызывать
new
илиdelete
в своем пользовательском коде. RAII - очень распространенный метод, который в значительной степени решает проблему управления ресурсами. Каждый ресурс в вашей программе (ресурс - это все, что необходимо получить, а затем освободить: дескрипторы файлов, сетевые сокеты, соединения с базой данных, а также обычное выделение памяти и, в некоторых случаях, пары вызовов API (BeginX ( ) / EndX (), LockY (), UnlockY ()) должны быть заключены в класс, где:new
если ресурс является выделением памяти)Этот класс затем создается локально, в стеке или как член класса, а не путем вызова
new
и сохранения указателя.Вам часто не нужно определять эти классы самостоятельно. Контейнеры стандартной библиотеки также ведут себя таким образом, что любой объект, сохраненный в a,
std::vector
освобождается при уничтожении вектора. Так опять же , не хранить указатель в контейнер (который требовал бы вы назватьnew
иdelete
), а , скорее , объект сам (который дает вам управление памятью бесплатно ). Аналогично, классы интеллектуальных указателей можно использовать для простого переноса объектов, которые просто должны быть выделеныnew
, и управления их временем жизни.Это означает, что когда объект выходит из области видимости, он автоматически уничтожается, а его ресурс освобождается и очищается.
Если вы будете делать это последовательно по всему коду, у вас просто не будет утечек памяти. Все, что могло вытечь, связано с деструктором, который гарантированно будет вызван, когда управление покидает область, в которой был объявлен объект.
источник
AddressSanitizer (ASan) - это быстрый детектор ошибок памяти. Он находит ошибки переполнения use-after-free и {heap, stack, global} -buffer в программах на C / C ++. Находит:
Этот инструмент очень быстрый. Среднее замедление инструментальной программы составляет ~ 2x.
источник
В дополнение к инструментам и методам, представленным в других разделах, инструменты статического анализа кода могут использоваться для обнаружения утечек памяти (а также других проблем). Бесплатный надежный инструмент - Cppcheck. Но есть много других доступных инструментов. В Википедии есть список инструментов для статического анализа кода.
источник
Убедитесь, что вся куча памяти успешно освобождена. Нет необходимости, если вы никогда не выделяете память в куче. Если вы это сделаете, подсчитайте, сколько раз вы использовали память malloc, и подсчитайте, сколько раз вы освобождаете память.
источник
Ни «new», ни «delete» никогда не должны использоваться в коде приложения. Вместо этого создайте новый тип, который использует идиому «менеджер / работник», в которой класс менеджера выделяет и освобождает память и перенаправляет все другие операции рабочему объекту.
К сожалению, это больше работы, чем должно быть, потому что в C ++ нет перегрузки «оператора». Еще больше работы при наличии полиморфизма.
Но это стоит потраченных усилий, потому что вам никогда не придется беспокоиться об утечках памяти, а значит, вам даже не придется их искать.
источник