Утечка памяти в с ++ - PullRequest
       14

Утечка памяти в с ++

6 голосов
/ 20 апреля 2009

Я запускаю свое приложение c ++ на устройстве Intel Xscale. Проблема в том, что когда я запускаю свое приложение вне цели (Ubuntu) с Valgrind , оно не показывает никаких утечек памяти.

Но когда я запускаю его на целевой системе, он начинается с 50КБ свободной памяти и уменьшается до 2К за ночь. Как отловить такую ​​утечку, которую не показывает Valgrind?

Ответы [ 9 ]

10 голосов
/ 20 апреля 2009

Распространенной причиной этих небольших встроенных устройств является фрагментация памяти. В вашем приложении может быть свободная память между 2 объектами. Распространенным решением этой проблемы является использование выделенного распределителя (оператора, нового в C ++) для наиболее распространенных классов. Пулы памяти, используемые исключительно для объектов размера N, не фрагментируются - пространство между двумя объектами всегда будет кратно N.

3 голосов
/ 20 апреля 2009

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

string s;
for (i=0; i<n; i++)
  s += "a";

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

3 голосов
/ 20 апреля 2009

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

Возможные способы преодоления этого:

  1. Разделить на два приложения. Главное приложение будет иметь простую логику с минимальным или нулевым использованием динамической памяти. Это заставит рабочее приложение фактически выполнять работу в таких блоках, что рабочему приложению не будет не хватать памяти, и он будет периодически перезапускать это приложение. Таким образом, память периодически возвращается в операционную систему.

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

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

1 голос
/ 20 апреля 2009

Это звучит как фрагментация. Фрагментация вызвана размещением объектов в стеке, например:

object1
object2
object3
object4

И затем удаление некоторых объектов

object1

object3
object4

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

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

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

Один из способов сделать это - создать одну статическую:

struct Slot
{
    Slot() : free(true) {}
    bool free;
    BYTE data[20];  // you'll need to tune the value 20 to what your program needs
};
Slot pool[500]; // you'll need to pick a good pool size too.

Создайте пул при запуске программы и предварительно выделите его так, чтобы он соответствовал максимальным требованиям для вашей программы. Возможно, вы захотите использовать HeapAlloc (или аналог в вашей ОС, чтобы вы могли контролировать, когда он появляется откуда-то при запуске приложения).

Затем переопределите операторы new и delete для подозрительного класса, чтобы они возвращали слоты из этого вектора. Итак, ваши объекты будут храниться в этом векторе.

Вы можете переопределить new и delete для классов того же размера, которые будут помещены в этот вектор.

Создание пулов разных размеров для разных объектов.

Сначала пойди на худших обидчиков.

Я делал что-то подобное раньше, и это решило мою проблему на встроенном устройстве. Я также использовал много STL, поэтому я создал собственный распределитель (google для stl custom allocator - есть множество ссылок). Это было полезно для записей, хранящихся в мини-базе данных, используемой моей программой.

0 голосов
/ 20 апреля 2009

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

0 голосов
/ 20 апреля 2009

Большинство приложений показывают схему использования памяти следующим образом:

  • они очень мало используют при запуске
  • когда они создают структуры данных, они используют все больше и больше
  • когда они начинают удалять старые структуры данных или повторно использовать существующие, они достигают устойчивого состояния, когда использование памяти остается примерно постоянным

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

0 голосов
/ 20 апреля 2009

Используете ли вы какую-либо сложную технику для отслеживания объема объекта? если да, то valgrind недостаточно умен, хотя вы можете попробовать установить параметр, связанный с xscale, с помощью valgrind

0 голосов
/ 20 апреля 2009

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

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

0 голосов
/ 20 апреля 2009

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

Все, что я могу добавить, это то, что Valgrind, как известно, довольно эффективно обнаруживает утечки памяти!

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