2014-01-19 2 views
3

Предположим, у меня была программа, как это:Каковы долгосрочные последствия утечек памяти?

int main(void) 
{ 
    int* arr = new int[x]; 
    //processing; neglect to call delete[] 
    return 0; 
} 

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

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

+3

Утечка памяти постоянно и бесполезно потребляет системные ресурсы, которые являются конечными. Разве это не достаточная причина? – Nemo

+0

Утечки памяти в худшем случае, когда они находятся в цикле. Подумайте о игре, которая повторяет цикл для каждого шага обновления и имеет утечку памяти в этом цикле. –

+4

Вы будете работать на низкой памяти, но до этого ваша система будет замедляться из-за подкачки – marcinj

ответ

6

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

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

Гораздо более серьезные утечки включают в себя:

  • где программа работает в течение длительного времени и потребляет больше памяти с течением времени, например фоновыми задачами на серверах, но особенно во встраиваемых устройствах, которые могут быть оставлены баллотируются много лет
  • где новая память выделяется часто для одноразовых задач, например, при рендеринге кадров компьютерной игры или анимированного видео
  • где программа может запрашивать память - такую ​​как разделяемая память - которая не освобождается, даже когда программа завершается
  • где память очень ограничена, например, во встроенной системе или портативного устройства
  • , где происходит утечка в пределах операционной системы или менеджера памяти
  • , когда системный драйвер устройства вызывает утечку
  • работает в операционной системе который автоматически не освобождает память при завершении программы. Часто на таких машинах, если память потеряна, ее можно восстановить только перезагрузкой, примером такой системы является AmigaOS.

Отъезд here для получения дополнительной информации.

-1

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

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

Также имейте в виду, что простое удаление не гарантирует отсутствие неиспользуемой памяти. Существуют различные аспекты от O.S. и сторона компилятора для управления этой функцией.

This link may help you a little And this one too

2

Скажем, у нас есть эта программа работает:

while(true) 
{ 
    int* arr = new int; 
} 

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

Вместо этого мы могли бы иметь эту программу, которая будет работать вечно, потому что нет никакой утечки памяти:

while(true) 
{ 
    int* arr = new int; 
    delete arr; 
} 

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

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

while(true) 
{ 
    int* arr = new int; 
    generateOxygenForAstronauts(); 
} 

Подумайте о космонавтах и ​​свободной памяти!

+0

Это не будет продолжаться до тех пор, пока не произойдет эта ошибка системы: завершение вызова после вызова экземпляра «St9bad_alloc» what(): std :: bad_alloc Aborted –

0

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

0

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

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

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

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

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

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

3

Существует основное предположение на ваш вопрос:

Роль delete и delete[] является исключительно, чтобы освободить память.

... и ошибочный.

Для лучше или хуже, delete и delete[] играют двойную роль:

  1. Run деструкторов
  2. Свободная память (вызывая правильную перегрузку operator delete)

с исправленным предположение, мы можем теперь задать исправленный вопрос:

В чем заключается риск не звонить delete/delete[], чтобы закончить время жизни динамически распределенных переменных?

Как уже упоминалось, очевидный риск - это утечка памяти (и, в конечном счете, сбой). Однако это наименьшее из ваших забот. Гораздо больше риск неопределенное поведение, что означает, что:

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

Последнее крайне тревожная:

  • Мьютексы: Забудьте снять блокировку, и вы получите a deadlock ...
  • Файловые дескрипторы: Некоторые платформы (например, FreeBSD, я считаю) имеют пресловутое ограничение по умолчанию для числа дескрипторов файлов, которые может открыть процесс; не удается закрыть дескрипторы файлов, и вы не сможете открыть какой-либо новый файл или сокет!
  • Сокеты: помимо дескриптора файла существует ограниченный диапазон портов, связанных с IP (который с последней версией Linux больше не является глобальным, да!). Абсолютный максимум составляет 65 536 (u16 ...), но эфемерный диапазон портов обычно намного меньше (половина его). Если вы забываете своевременно выпускать соединения, вы можете легко оказаться в ситуации, когда даже если у вас много доступной полосы пропускания, ваш сервер перестает принимать новые соединения, потому что нет доступного эфемерного порта.
  • ...

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

Конечно, вы могли бы сказать: Хорошо, я сосредоточусь на других ресурсах утечки, но инструменты в настоящее время сообщают о них, как утечка памяти (и это достаточно), чтобы изолировать эту утечку среди сотен/тысяч, как ищут иголку в стог сена ...

Примечание: я упомянул, что вы все еще можете не хватать памяти? Независимо от того, находятся ли на нижних машинах/системах или в ограниченной системе процессов/виртуальных машинах память может быть достаточно жесткой для этой задачи.

Примечание: если вы вызываете delete, вы делаете это неправильно. Научитесь использовать стандартную библиотеку std::unique_ptr и ее контейнеры std::vector. В C++ автоматическое управление памятью легко, реальная задача состоит в том, чтобы избежать оборванных указателей ...

Смежные вопросы