Подтвердить что ты не робот

Когда может произойти утечка памяти?

Я не знаю, что здесь думать...

У нас есть компонент, который работает как служба. Он отлично работает на моей локальной машине, но на какой-то другой машине (на обеих машинных операционных системах равны 2 ГБ) он начинает генерировать исключения bad_alloc во второй и последующие дни. Дело в том, что использование памяти в процессе остается неизменным на уровне примерно 50 Мб. Другая странная вещь заключается в том, что с помощью отслеживания сообщений мы локализуем исключение, которое должно быть выбрано из объекта stringstream, который делает, но вставляет в поток не более 1-2 Кбайт данных. Мы используем STL-порт, если это имеет значение.

Теперь, когда вы получаете исключение bad_alloc, вы считаете, что это утечка памяти. Но all наши ручные распределения переносятся в интеллектуальный указатель. Кроме того, я не могу понять, как объект stringstream не хватает памяти, когда весь процесс использует только ~ 50Mb (использование памяти остается приблизительно постоянным (и уверенно не растет) изо дня в день).

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

Итак, мой вопрос... Как может произойти утечка памяти /bad _alloc, когда процесс использует только память 50 МБ из 2 ГБ? Какие еще дикие предположения вы имеете относительно того, что может быть неправильным?

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

4b9b3361

Ответ 1

bad_alloc не обязательно означает, что памяти недостаточно. Функции распределения также могут не работать, потому что куча повреждена. Возможно, у вас есть переполнение буфера или запись кода в удаленную память и т.д.

Вы также можете использовать Valgrind или одну из заменой Windows найти утечку/переполнение.

Ответ 2

Одна из возможных причин в вашем описании состоит в том, что вы пытаетесь выделить блок из нескольких необоснованно больших размеров из-за ошибки в коде. Что-то вроде этого;

 size_t numberOfElements;//uninitialized
 if( .... ) {
    numberOfElements = obtain();
 }
 elements = new Element[numberOfElements];

теперь, если numberOfElements оставлен неинициализированным, он может содержать некоторое неоправданно большое число, и поэтому вы эффективно пытаетесь выделить блок из 3 ГБ, который менеджер памяти отказывается делать.

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

Ответ 3

Просто догадаться,

Но у меня были проблемы в прошлом при распределении массивов таким образом

int array1[SIZE];  // SIZE limited by COMPILER to the size of the stack frame

когда SIZE является большим числом.

Решение заключалось в том, чтобы выделить новый оператор

int* array2 = new int[SIZE];  // SIZE limited only by OS/Hardware

Я нашел это очень запутанным, причина оказалась структурой стека, как обсуждалось здесь в решении Мартина Йорка: Есть ли максимальный предел длины массива в С++?

Все самое лучшее,

Tom

Ответ 4

Проверьте профиль других процессов на машине, используя Process Explorer из sysinternals - вы получите bad_alloc, если память коротка, даже если это не вы, которые вызывают давление в памяти.

Проверьте использование собственной памяти с помощью umdh, чтобы получить моментальные снимки и сравнить профиль использования с течением времени. Вам нужно будет сделать это в начале цикла, чтобы не взорвать инструмент, но если ваше поведение процесса не ухудшается с течением времени (то есть без внезапного патологического поведения), вы должны получить точную информацию об использовании памяти в момент времени T vs time T+t.

Ответ 5

Я не понимаю, почему поток будет бросать. У вас нет сброса неудачного процесса? Или, возможно, подключить к нему отладчик, чтобы узнать, что распределитель пытается выделить?

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

Только мои 2 (евро) cts...

1. Фрагментация?

Память может быть фрагментирована.

В какой-то момент вы пытаетесь выделить байты SIZE, но распределитель не находит непрерывного блока байтов SIZE в памяти, а затем бросает bad_alloc.

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

2. подписанный против без знака?

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

char * p = new char[i] ;

Если значение i отрицательно (например, -1), приведение в неподписанный интеграл size_t приведет к тому, что он выходит за пределы того, что доступно для распределителя памяти.

Поскольку использование подписанного интеграла довольно часто встречается в коде пользователя, если его использовать только как отрицательное значение для недопустимого значения (например, -1 для неудачного поиска), это возможность.

Ответ 6

Еще один длинный снимок: вы не говорите, в какой из трех операций происходит ошибка (конструкция, << или журнал), но проблема может быть фрагментацией памяти, а не потреблением памяти. Возможно, stringstream не может найти непрерывный блок памяти достаточно долго, чтобы удержать пару килобайт.

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

Ответ 7

 ~className(){

 //delete stuff in here

}

Ответ 8

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

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