Должен ли я освобождать память перед выходом?

Должен ли я освобождать всю свою разделяемую память, когда я выхожу из программы из-за ошибки?

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

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