Страницы

Поиск по вопросам

воскресенье, 8 декабря 2019 г.

Освобождение динамической памяти перед завершением

#cpp #c #memory_leaks


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

Единственный ответ, до которого мы с коллегами пришли: чтобы "зомби" (в Linux), если
он появится после завершения программы, занимал минимальное место.

В остальных случаях ОС сама подотрет все, что было занято, разве нет? 

Какие еще негативные последствия могут возникнуть?
    


Ответы

Ответ 1



Зомби (в *nix) места в памяти не занимает (в том смысле, который вы в это вкладываете). Он занимает одну запись в стуктуре планировщика в ядре. А так, да, нормальная современная ОС (в которых почти все пишут) "все подотрет" за процессом. Почти все. С сегментами shared memory проблемы будут, но это в лоб не автоматизируется, поскольку удалять или оставлять -- зависит от сути прикладной задачи. Если же вдруг будете писать программы под что-то другое (какой-нибудь самодельный монитор для real-time embedded), то может и придется убирать память самому.

Ответ 2



Смотрите. Никаких причин освобождения памяти перед завершением программы, кроме чисто эстетических, нет. Память всё равно вернётся системе после смерти процесса. Однако, довольно часто объекты в своём деструкторе совершают дополнительные действия. Закрывают транзакцию в базе данных, корректно закрывают онлайн-сессию, сбрасывают изменённые данные на диск и т. п. Таким образом, если такой объект «утечёт», то программа после завершения оставит что-то в некорректном состоянии. Если ваша программа маленькая, вы можете её полностью обозреть, и вы уверены, что кроме утечек памяти ничего плохого от пропущенных деструкторов не случится — можете смело оставлять в конце память. Но если ваш проект большой, то скорее всего у вас не будет полного обзора того, что какой модуль делает. В такой ситуации лучше придерживаться дисциплинированного подхода и чистить за собой.

Ответ 3



Перед завершением работы программы нужно убедиться, что разделяемые ресурсы освобождены, например, соединения с базой данных и веб-серверами закрыты. Серверы какое-то время могут считать ваш клиент всё ещё подключенным, что нежелательно. Следует сбросить данные на диск в файлах, если вам есть дело до их содержимого. Если вам всё равно, то можно не закрывать — система справится сама. Освобождать память обычно ненужно, хоть это и является правилом хорошего тона. Более того, если ваша программа выделила очень много сложных объектов в памяти, и память частично свалилась в своп, то может быть выгодно не освобождать память, чтобы не заставлять систему вытаскивать информацию с диска только для того, чтобы её выбросить. Если вы хотите быстро завершить процесс, то можете аккуратно разрушить объекты, которые хранят ссылки на разделяемые ресурсы, а потом просто убить процесс. Более того, в идеале программа должна корректно обрабатывать случай убийства процесса в любой момент. Данные при этом не должны быть повреждены. Отработка случая жёсткого убийства процесса без аккуратного освобождения памяти и ресурсов — это важный момент при разработке программ. Из-за этого ваша программа не должна перестать быть работоспособной (например, из-за повреждения конфигурационных файлов).

Ответ 4



Код на C работает в таких местах где никакой ОС может вообще не существовать и в помине. Компьютерная память является общим ресурсом, крайне сложным и дорогим в производстве. Не стоит думать что она принадлежит лично Вам. Например в данный момент на хосте откуда я пишу вам это сообщение запущено 106 процессов, написанных другими людьми(физически они все используют DDR за которую заплатил лично я). Представьте что было бы с ними если бы автор каждого из них думал только о себе и не занимался высвобождением памяти, а наоборот пытался схватить её как можно больше будучи одержимым идеей об уникальноси и сверхполезности своей поделки. Момент прекращения использования того или иного ресурса в программе(в частности памяти) может не совпадать с её завершением. Но если вы пишите какую-то мелкую прикладную программу для популярной ОС в которой при этом еле еле аллокируется 100кБ, то можно конечно понадеется и на ОС и на язык с автоматической сборкой мусора. В принципе ничем страшным это не грозит, если конечно программа внезапно не разрастется до больших размеров и толпы пользователей в придачу. Тогда однозначно стоит начинать более серьезно задумываться о распределении общих ресурсов, в частности и памяти.

Ответ 5



В C++ операторы delete и delete[], которыми Вы освобождаете память, вызывают деструкторы объектов. Если в деструкторе есть какая-то логика (например, сериализация), она не сработает, и какие-то данные могут быть потеряны. Замечу так же, что функция free деструктор не вызывает, ее задача - освободить память. Обычно освобождение памяти считается хорошим тоном. Даже если у Вас нет в деструкторах логики сейчас, это не значит, что ее не появится там в будущем (и тогда придется перелопатить весь проект). Если Ваша программа завершается в этом месте сейчас, то это не значит, что в будущем она не будет завершаться гораздо позже (и Вы получите уже значимую утечку памяти). То есть, выполняя очистку памяти, Вы получаете меньше проблем в будущем. Программа становится более расширяемой и поддерживаемой. Однако, бывает, что память не освобождается специально. Например, в C++ имеется проблема с порядком инициализации/деинициализации статических переменных, которая при выявлении часто решается при помощи синглтона. Такой синглтон должен существовать и после завершения функции main, так как после как раз и происходит деинициализация статических переменных. Поэтому он создается при помощи new и никогда не освобождается.

Комментариев нет:

Отправить комментарий