Должен ли я освобождать память перед выходом?
Должен ли я освобождать всю свою разделяемую память, когда я выхожу из программы из-за ошибки?
something = (char**) malloc (x * sizeof(char*));
for (i = 0; i < x; i++)
something[i] = (char*) malloc (y + 1);
...
if (anything == NULL) {
printf("Your input is wrong!");
// should I free memory of every mallocated entity now?
exit(1);
}
else {
// work with mallocated entities
...
free(something); // it must be here
system("pause);
}
Ответы
Ответ 1
Это зависит от ОС. Лучшая практика, я бы сказал, что вы должны явно освободить ее. Это также делает использование таких инструментов, как valgrind, PITA, если у вас нет свободной памяти, и я не могу сказать, что хорошо и что плохо и т.д.
Если в ОС, которая явно освобождает память, у вас все еще есть проблема с другими ресурсами. Когда ваше приложение начинает расти и загружать сторонние библиотеки, вы можете получить утечку ресурсов. Представьте, что я написал библиотеку, которая просит, чтобы вы вызывали close на обработчике. Этот обработчик поддерживается временными файлами, которые не удаляются, пока вы не вызовете close. Или я отключил процессы, которые работают в фоновом режиме, которыми я управляю, используя сигналы или какой-то другой ресурс, о котором вы не знаете.
Ответ 2
На самом деле это действительно сложный, невесомый вопрос.
Pro (за освобождение всего перед выходом):
- никаких ошибок или утечек памяти позже, если код переставлен
- нет ложных срабатываний от Valgrind или проверки утечки памяти
- нет утечек памяти, если вы работаете под ошибочной ОС, или вообще нет ОС
Кон (просто выйдите, не беспокойтесь о том, чтобы освободить все):
- освободить все может быть много работы
- освобождение всего может привести к ошибкам и сбоям
- ваша операционная система действительно должна вернуть вам все ресурсы, когда вы выходите
И еще один момент (не уверен, что это "за" или "против"): на большинстве систем вызов free
не возвращает память операционной системе (это делает только выход).
В конце концов, вам придется решить, какие из этих плюсов и минусов важнее всего для вас. Разные программисты в разных проектах при разных обстоятельствах придут к разным выводам; здесь нет единого ответа на все вопросы.
Смотрите также этот предыдущий вопрос Кару.
См. также вопрос 7.24 в списке часто задаваемых вопросов C.
Ответ 3
Вам не нужно освобождать память до завершения программы. Прекращение программы в любом случае приводит к автоматическому освобождению всей памяти.
Ответ 4
Вы должны всегда освобождать выделенную память перед выходом. Как уже упоминалось в других ответах, это минимизирует предупреждения от инструментов статического или динамического анализа и т.д.
Но реальная причина, по которой вы всегда должны это делать, заключается в том, что освобождение часто предоставляет скрытые ошибки времени выполнения в вашем приложении.
Если у вас есть ошибка где-то, что приводит к повреждению памяти или изменению адресов указателей, эта ошибка может оставаться безмолвной и спящей. Пока вы не измените что-то совершенно не связанное с ошибкой и тем самым перетасовываете макет памяти. Затем внезапно вы получите сбой, и вы не поймете, почему, потому что ошибка даже не находится в коде, который вы только что добавили.
Освободив память, вы вызываете такие ошибки на поверхность. Потому что, если что-то не так с кучей или с указателями, указывающими на кучу, тогда вы часто получите сбой в точке, где вы вызываете free()
. Это означает, что у вас есть серьезная ошибка где-то, что вам нужно найти перед отправкой программы.
Ответ 5
У меня был совершенно противоположный сценарий: деструкторы-сегрегаторы статических объектов из сторонней библиотеки. Просто из-за явного освобождения пулов памяти перед выходом.
Полагаю, лучше быть разумным и сосредоточиться на структуре программы.