Найти огромные блоки выделенной памяти - PullRequest
4 голосов
/ 02 апреля 2012

У меня есть программа (демон), написанная на c / c ++.Он работает без нареканий, но через некоторое время (это может быть 5 дней, неделя, 2 недели) он начинает выделять много мегабайт памяти.Я не могу понять, какие части кода не освобождают выделенную память.При запуске использование памяти составляет около 20-30 мегабайт.Затем, после некоторого периода или, возможно, события, он медленно увеличивается примерно до 1 МБ в час, и, если его не остановить, может произойти сбой, так как нет доступной памяти.

Я попытался использовать Valgrind и отключил демон обычным способом, когда он уже выделил около 500 МБ памяти.Процесс выключения был действительно долгим, но когда он закончился, Вэлгринд сказал, что утечек памяти не обнаружено, за исключением процедур mysql_init / mysql_close (определенно потеряно около 504 байт).Google говорит, что не стоит беспокоиться об этой утечке Mysql, и приводит несколько причин, по которым такие инструменты диагностики памяти, как Valgrind, считают, что это утечка.

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

Ответы [ 3 ]

4 голосов
/ 02 апреля 2012

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

Во-первых, все объекты и память освобождаются при выключении.Если есть утечка, valgrind обнаружит ее как память, на которую не ссылается объект и т. Д. Любые утечки, тем не менее, будут устранены операционной системой.

Если вы перехватываете все исключения (...)и не делать с ними ничего, ну, не делай этого.Это частая причина.

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

Немного проще, вы можете использовать глобальную переменную, каждый ctor может увеличивать ее на 1, а dtor уменьшать на 1. Если вы обнаружите, чтоколичество объектов не остается относительно одинаковым, вы можете выяснить, какие из них создают проблему, используя аналогичные методы.

В-третьих, используйте Boost и его интеллектуальные указатели с заданными областями, чтобы помочь, но не полагайтесь на интеллектуальные указатели, так какСвятой Грааль.

Есть возможная причина, с которой я столкнулся.Для долго выполняющихся программ фрагментация памяти может привести к большому использованию памяти.Вы можете удалить объект размером 1 МБ, а затем попытаться создать объект размером 2 МБ;создание будет в новом пространстве, потому что 1 МБ «свободный кусок» недостаточно велик.Затем, когда вы создаете объект размером 512 КБ, он может войти в пространство этого объекта размером 1 МБ, используя только половину доступного пространства, но сделав его так, чтобы ваш следующий объект размером 1 МБ был размещен в большом пространстве.

К сожалению, этопроблема может стать плохой из-за небольших объектов, размещенных в постоянных местах.Скажем, в памяти могут быть 50-байтовые классы, разделенные на 300 КБ, и примерно 100 из них, но объекты 512 КБ не могут быть выделены в этом пространстве, поэтому он выделяет дополнительные 512 КБ для каждого нового объекта, эффективно тратя 90% фактического ».свободного места, даже если вашей программе уже принадлежит более чем достаточно.

Эту проблему трудно отследить как определенную причину, но если вы изучаете поток вашей программы, ищите небольшие выделения.Запомните std :: list / vector / etc.может все это вызвать;если вы хотите, чтобы демон выполнял много операций с памятью в течение нескольких недель, рекомендуется предварительно выделить память с помощью Reserve ().Пулы памяти еще лучше.

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

3 голосов
/ 03 апреля 2012

Попробуйте использовать инструмент Valgrind Massif. С Массив ручной :

Кроме того, существуют определенные утечки пространства, которые не обнаруживаются традиционные средства проверки герметичности, такие как Memcheck's. Это потому что память никогда не теряется - указатель остается на ней - но это не используется. Программы, которые имеют такие утечки, могут излишне увеличить объем памяти, которую они используют с течением времени. Массив может помогите выявить эти утечки.

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

1 голос
/ 02 апреля 2012

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

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

struct list{
DATA_ARRAY arr; //Some data 
struct *list next;
};

While(true) //infinite loop
{
// Add new nodes to list 
// Store some data in the node
}

Здесь нет утечки. Но цикл добавляет новые узлы навсегда и хранит данные, и все отлично работает. Но использование памяти все время увеличивается. Поскольку вы работаете в течение 2-5 дней, нечто подобное, безусловно, возможно.

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

...