ОС просто восстановит его (после выхода из программы), верно? Так какая же от этого польза, кроме хорошего стиля программирования? Или я что-то недопонимаю? Что отличает его от «автоматического» распределения, поскольку оба они могут быть изменены во время выполнения и оба завершаются после выполнения программы?
Действительно ли нам нужно использовать функцию free(), когда мы используем malloc()? Чем же тогда она отличается от автоматической переменной?
Ответы (8)
Когда ваше приложение работает с огромными объемами данных, вы должны освободить память, чтобы сохранить место в куче. Если вы этого не сделаете, может произойти несколько плохих вещей:
- ОС перестанет выделять вам память (вылетает)
- ОС начнет подкачивать ваши данные на диск (прокручивая)
- у других приложений будет меньше места для размещения своих данных
Тот факт, что ОС собирает все пространство, которое вы выделяете при выходе из приложения, не означает, что вы должны полагаться на это при написании надежного приложения. Это все равно, что пытаться полагаться на компилятор для оптимизации плохого программирования. Управление памятью имеет решающее значение для хорошей производительности, масштабируемости и надежности.
Как уже упоминалось, malloc выделяет место в куче, а автоматические переменные создаются в стеке. Есть применения для обоих, но они действительно очень разные. Пространство кучи должно быть выделено и управляться операционной системой и может динамически хранить данные разных размеров.
Если вы вызываете макрос тысячу раз без использования free(), то компилятор или с уверенностью можно сказать, что система назначит вам тысячу разных адресов, но если вы используете free() после каждого malloc, то каждый раз вам будет даваться только один адрес памяти. Таким образом, шансы на утечку памяти, ошибку шины, выход за пределы памяти и сбой будут минимальными. Безопасно использовать free().
В C/C++ автоматические переменные размещаются в стеке. Они уничтожаются прямо на выходе из функции. Это произойдет автоматически. Для этого не нужно ничего писать.
Выделения кучи (результат вызова malloc) либо освобождаются явно (с вызовом free), либо очищаются при завершении процесса.
Если вы пишете небольшую программу, которая будет использована один или два раза, то можно не освобождать память в куче. Это не красиво, но приемлемо.
Если вы пишете средний или большой проект или планируете включить свой код в другой проект, вам обязательно следует освобождать каждое выделение кучи. Невыполнение этого создаст ОГРОМНЫЕ проблемы. Куча памяти не бесконечна. Программа может использовать все это. Даже если вы выделите небольшой объем памяти, это все равно создаст ненужную нагрузку на ОС, приведет к свопингу и т.д.
Итог: освобождение аллокаций — это гораздо больше, чем просто стиль или хорошая привычка.
Автоматическая переменная уничтожается (и ее память можно использовать повторно), как только вы выходите из области, в которой она определена. Для большинства переменных это намного раньше выхода из программы.
Если вы malloc и не free, то память не может быть повторно использована до выхода из программы. Даже тогда, на некоторых системах с очень минимальной ОС.
Так что да, есть большая разница между автоматической переменной и выделением памяти с утечкой. Вызовите функцию, которая пропускает выделение достаточное количество раз, и у вас закончится память. Вызывайте функцию с автоматической переменной столько раз, сколько хотите, память можно использовать повторно.
Это хороший стиль программирования и даже больше. Отсутствие надлежащего управления памятью в нетривиальных программах в конечном итоге повлияет на удобство использования вашей программы. Конечно, ОС может восстановить любые ресурсы, которые вы выделили/использовали после завершения вашей программы, но это не облегчает нагрузку или потенциальные проблемы во время выполнения программы.
Рассмотрим веб-браузер, который вы использовали для публикации этого вопроса: если браузер написан на языке, который требует управления памятью, и код не делает это должным образом, как вы думаете, сколько времени пройдет, прежде чем вы заметите что он съедает всю твою память? Как долго, по вашему мнению, браузер будет оставаться пригодным для использования? Теперь учтите, что пользователи часто оставляют браузеры открытыми на длительное время: без надлежащего управления памятью они станут непригодными для использования после несколько загрузок страниц.
Если ваша программа не завершается немедленно, и вы не освобождаете свою память, вы в конечном итоге потратите ее впустую. Либо у вас в конце концов закончится память, либо вы начнете переключаться на диск (что медленно, а также не без ограничений).
автоматическая переменная находится в стеке, и ее размер должен быть известен во время компиляции. если вам нужно хранить данные, размер которых вам не подходит, например, поддерживайте двоичное дерево, где пользователь добавляет и удаляет объекты. кроме того, размер стека может быть ограничен (зависит от вашей цели), например, для ядра Linux стек обычно составляет 4k-8k. вы также уничтожаете кеш инструкций, что влияет на производительность,
Да, вам абсолютно необходимо использовать free() после malloc() (а также закрывать файлы и другие ресурсы, когда вы закончите). Хотя верно то, что ОС восстановит его после выполнения, длительный процесс приведет к утечке памяти таким образом. Если ваша программа так же проста, как основной метод, который запускает один метод, а затем существует, это, вероятно, не имеет большого значения, хотя и невероятно небрежно. Вы должны выработать привычку правильно управлять памятью в C, потому что однажды вам может понадобиться написать нетривиальную программу, которая выполняется дольше секунды, и если вы не научитесь делать это заранее, у вас будет огромная головная боль, связанная с утечками памяти.