Как отладить странную утечку памяти (C ++) - PullRequest
3 голосов
/ 23 февраля 2010

Я пишу демон linux, и на данный момент он работает довольно хорошо, но он теряет память (и это плохо - через несколько часов происходит сбой после использования 60% системной памяти). Странно то, что я использую только операторы new / delete и у меня есть блок try / catch вокруг основной функции, так что это не исключение, генерируемое new - это просто segfaults в какой-то момент из-за нехватки памяти, я думаю .

Я использовал valgrind, но он обнаружил единовременную небольшую утечку и ничего больше. Я тоже попробовал gdb, но, хотя приложение скомпилировано с флагами -g -rdynamic, оно не переводит все адреса в имена функций.

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

Ответы [ 8 ]

4 голосов
/ 23 февраля 2010

Valgrind обычно очень надежен в поиске утечек, так что вы уверены, что это утечка памяти?

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

3 голосов
/ 24 февраля 2010

«Утечка памяти» на языке C ++ относится к потерянной памяти, которая не была освобождена, но больше недоступна. Если валгринд говорит, что у вас нет утечек , то вы, вероятно, сохраняете указатели на объекты, которые вам больше не нужны. Строго говоря, это не утечка, но в конечном итоге это приведет к увеличению объема используемой памяти.

Если вы хотите использовать valgrind, передайте флаг --show-reachable, чтобы он сбрасывал все объекты, которые все еще доступны в памяти на момент выхода из вашего приложения. Затем вы можете просмотреть эти следы стека и определить, какие объекты хранятся в памяти слишком долго и почему.

0 голосов
/ 24 февраля 2010

Однажды я прочитал, что иногда new будет возвращать NULL, если у вас закончится память, а не выбрасывать исключение Может быть, это вызывает segfault?

0 голосов
/ 24 февраля 2010

вы получаете какие-то странные предупреждения от вашего компилятора или компоновщика ?? что-нибудь связанное с libstdc ++? у нас была проблема, когда мы одновременно связывались с двумя отдельными версиями libstdc ++ (5 и 6), и это приводило к ужасным утечкам памяти.

0 голосов
/ 24 февраля 2010

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

Почти каждая «утечка», которую я отлаживал, особенно в Java, была результатом неограниченного роста стандартной коллекции. т.е. векторы, которые никогда не очищаются, словари, которые растут сверх ожиданий и т. д. Если Valgrind ничего не находит, есть хороший шанс, что это не настоящая утечка.

0 голосов
/ 24 февраля 2010

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

0 голосов
/ 24 февраля 2010

Я советую вам сначала попытаться решить вашу проблему с помощью gdb, поскольку это инструмент № 1, позволяющий выяснить, что происходит при возникновении ошибки. Затем запустите вашу программу до ее сбоя и убедитесь, что система генерирует файл ядра (используйте ulimit -c unlimited, чтобы разрешить создание файла ядра, будьте осторожны, если это демон, это должно быть сделано для пользователя, который фактически запускает демон). На этом этапе вы можете использовать gdb с файлом ядра, чтобы выяснить, где произошла ошибка (см. backtrack команда).

0 голосов
/ 24 февраля 2010

Как уже отмечали другие, это, вероятно, не простая утечка. Скорее всего, это неправильное принудительное приведение, которое заставляет его неправильно интерпретировать тип какого-либо объекта. Или буфер в / переполнение, или целочисленное переключение (какое-то 32-битное смещение со знаком, превышающее 2Gig?), Или висячий указатель ....

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

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