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

Что такое утечка памяти?

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

Итак, вот что я (думаю) понимаю. Исправления очень приветствуются!

При первом запуске программы выделяется блок памяти, скажем от 0x000 до 0xFFF. Первая часть (скажем от 0x000 до 0x011) - это сегмент кода/текста, где загружен программный код.

+--------------+ 0x011
| Program Code |
+--------------+ 0x000

Затем у вас есть стек (от 0x012 до 0x7ff), который содержит локальные переменные, и они сохраняются/извлекаются FIFO. Поэтому, если у вас есть что-то вроде

char middleLetter(string word){
     int len = word.length();
     return word[len/2];
}

int main(){
   int cool_number;
   char letter;
   letter = middleLetter("Words");
   ...

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

+-------------+ 0x7ff
|             |
|             |
|             |
| ...         |
| len         |
| letter      |
| cool_number |
+-------------+ 0x012

Конечно, если вы где-то выделяли память (используя malloc или new), но никогда не освобождая ее, тогда ваша куча могла бы выглядеть так, и теперь у вас есть утечка памяти:

+-------------+ 0xfff
|             |
| malloc(20)  | 0xf64
| malloc(50)  | 0xf32
| malloc(50)  | 0xf00
| ...         |
|             |
+-------------+ 0x800

Это означает, что, хотя вы можете напрямую обращаться к 0xf32 с помощью арифметики указателя, OS/ваша программа думает, что ячейки памяти 0xf00-0xf46 уже приняты и больше не будут использовать эти места для хранения, пока ваша программа не будет закрыт и память освобождается. Но как насчет общей памяти? Википедия говорит, что он никогда не будет выпущен (пока ваш компьютер не будет перезапущен?). Откуда вы знаете, если он разделяет память?

Это довольно хорошее базовое понимание? Есть ли что-то, что мне не хватает/не так? Спасибо, что посмотрели!

4b9b3361

Ответ 1

Похоже, вы понимаете это - за одним исключением: в вашем примере len - это переменная стека, как и все остальное. new или malloc создаются в куче, все остальное (локальные переменные и т.д.) находится в стеке. И основные локальные переменные не отличаются от любых других переменных функции.

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

Ответ 2

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

  • Вызов некоторой функции F
  • F выделяет (новую или malloc) некоторую память
  • F возвращается к вызывающему абоненту (без удаления/бесплатного)
  • указатель, указывающий на динамически выделенную память, выходит за рамки
    • память все еще выделена.
    • Больше не удалять/освобождать

Ответ 3

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

Давайте рассмотрим типичное приложение, скажем, читателя новостей RSS. В таком приложении часто бывает много циклов (цикл через разные RSS-каналы, разные элементы RSS, теги RSS и т.д.). Если у вас есть экземпляр, где созданный объект не был должным образом уничтожен (или выпущен), каждый раз, когда выполняется этот "протекающий" код, вы завершаете работу с другим заброшенным объектом в памяти. Если цикл работает 1000 раз, у вас будет 1000 заброшенных объектов, занимающих место. Вы можете увидеть, как это может быстро добавить к потреблению ценных ресурсов.

Ответ 4

Произошла утечка памяти: всякий раз, когда вы выделяете память с помощью malloc/new и не освобождаете ее позже, после бесплатного удаления после завершения использования этой памяти... приведет к утечке памяти! Выделенная память останется там, и это пространство больше не будет использоваться вашей программой.

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

Ответ 5

В общем случае автоматические переменные в функциях (подпрограммах) также будут храниться в стеке. Только "malloc" или "новые" распределения данных поступают из кучи. Далее, распределения на основе кучи могут быть освобождены и повторно использованы (много раз) до конца программы. Система распределения отслеживает как используемые области, так и освобожденные районы. Наконец, утечка памяти - это когда ваша программа потеряла часть выделенной памяти, не освобождая ее. это может произойти путем записи поверх указателя с новым значением или сохранения указателя в переменной с ограниченным сроком службы/областью.

Ответ 6

Похоже, вы используете код на С++. В С++ локальные переменные помещаются в стек (я предполагаю, что глобальные переменные тоже, но я не уверен). Так что len в вашей функции middleLetter будет также помещаться в стек вызовов. Я рекомендую прочитать эту статью: http://en.wikipedia.org/wiki/Call_stack

Когда вы используете новый оператор с типом, например, int *x = new int;, достаточно найти достаточную непрерывную память для ввода int. Указатель, который вы используете для его ссылки, * x, является локальной переменной. Если x выходит за пределы области действия и вы теряете указатель, это не освобождает память в куче. Эта память по-прежнему "используется" вашей программой, даже если у вас нет способа ссылаться на нее. Поскольку вы не можете ссылаться на него, вы не можете его освободить (или удалить).

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

Ответ 7

В сборках с мусором термин "утечка памяти" иногда может казаться немного туманным. Я бы предложил следующее определение, которое так же применимо к сборщикам мусора, что и для тех, которые используют явное освобождение: Программа или подпрограмма P имеет утечку памяти, если существует исходная последовательность входов S и повторяющаяся структура входов P, такая что:

  • Подача программы или входа подпрограммы S, за которой следует P, оставит программу в том же "значимом" состоянии, что и до P, но
  • Для любого количества памяти Q существует некоторое число N повторений, так что подача программного ввода S, за которым следуют N повторений P, заставит программу использовать больше, чем количество Q памяти.

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