Освобождение динамически выделяемой памяти - PullRequest
7 голосов
/ 18 июля 2010

В C ++, когда вы создаете новую переменную в куче следующим образом:

int* a = new int;

вы можете сказать C ++ вернуть память, используя delete следующим образом:

delete a;

Однако, когда ваша программа закрывается, автоматически ли она освобождает память, которая была выделена новой?

Ответы [ 6 ]

6 голосов
/ 18 июля 2010

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

Таким образом, необходимо тщательно управлять памятью и освобождать динамически распределяемые данные с соответствующим значением delete для каждого new (или delete [] при использовании new []), как только вам больше не требуется указанная переменная.

3 голосов
/ 18 июля 2010

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

2 голосов
/ 18 июля 2010

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

То есть, если вы динамически распределяете что-то, но никогда не освобождаете это, вы просочились. Он может закончить свой срок жизни только после того, как вы назовете delete / delete[]. На некоторых ОС (и почти на всех настольных ОС) память будет восстановлена ​​(поэтому другие программы могут ее использовать). Но память не такая же, как ресурс! ОС может освободить всю память, которую она хочет, если у вас есть какое-либо сокетное соединение для закрытия, какой-то файл для завершения записи и т. Д., ОС может этого не делать. Важно не допустить утечки ресурсов. Я слышал о некоторых встроенных платформах, которые даже не освобождают память, которую вы не освободили, что приводит к утечке до перезагрузки платформы.

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

Так что не используйте new T[N], используйте std::vector<T> v(N);. Последний не допустит утечку ресурсов. Не используйте new T;, используйте smart_ptr p(new T);. Умный указатель будет отслеживать объект и удалять его, когда он будет использоваться дольше. Это называется областным управлением ресурсами (SBRM, также называемое тупым именем Resource-Acquisition is Initialization или RAII.)

Обратите внимание, что нет единственного "smart_ptr". Вы должны выбрать, какой из них лучше. Текущий стандарт включает std::auto_ptr, но он довольно громоздкий. (Его нельзя использовать в стандартных контейнерах.) Лучше всего использовать часть умных указателей Boost или TR1, если ваш компилятор поддерживает это. Тогда вы получите shared_ptr, возможно, самый полезный умный указатель, но есть много других.

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

1 голос
/ 18 июля 2010

Нет, когда программа закрывается («закрывается»), динамически выделенная память остается как есть

EDIT:

Читая другие ответы, я должен быть более точным. Деструкторы динамически размещаемых объектов не будут работать, но память все равно будет восстановлена ​​любой приличной ОС.

PS: первая строка должна читать

int* a = new int;
1 голос
/ 18 июля 2010

Нет, это ваша обязанность освободить его.Кроме того, a должен быть указателем, поэтому он должен быть:

int *a = new int;
delete a;

Этот отличный ответ Брайана Р. Бонди подробно объясняет, почему рекомендуется освобождать память, выделенную a.

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

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

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

0 голосов
/ 18 июля 2010

Когда ваш процесс завершается, ОС восстанавливает контроль над всеми ресурсами, которые он использовал, включая память. Однако это, конечно, не приведет к обязательному запуску деструкторов C ++, так что это не панацея от явного освобождения указанных ресурсов (хотя, конечно, это не будет проблемой для int или других типов с noop dtors ; -).

...