Должен ли каждый вызов malloc быть освобожден - PullRequest
7 голосов
/ 02 декабря 2010

Из того, что я понимаю, потому что malloc динамически назначает mem, вам нужно освободить эту mem, чтобы ее можно было использовать снова.

  1. Что произойдет, если вы вернете символ *, созданный с помощью malloc (т.е. как вы должны освободить это)
  2. Если оставить указатель как есть и выйти из приложения это будет освобожден. (Я не могу найти однозначного ответа на этот вопрос, некоторые говорят, что да, некоторые говорят, что нет).

Ответы [ 9 ]

7 голосов
/ 02 декабря 2010
  1. Если у вас есть указатель на память, созданный malloc, free, то использование этой памяти, используя этот указатель, будет работать правильно.Да, в этом есть какая-то магия;об этом позаботится ваш компилятор.

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

7 голосов
/ 02 декабря 2010
  1. Вызывающий должен освободить его (или организовать его освобождение).Это означает, что функции, которые создают и возвращают ресурсы, должны документировать, как именно они должны быть освобождены.

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

Основными причинами освобождения его до этого являются:

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

Неопределенные причины для освобождения:

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

Причины освобождения почти всегда перевешивают причины против.

4 голосов
/ 02 декабря 2010

Да.Если вы malloc, вам нужно бесплатно.Вы гарантируете утечки памяти во время работы вашей программы, если вы не освобождаете ее.

Освободите ее.

Всегда.

Период.

2 голосов
/ 02 декабря 2010

Если вы пишете функцию самостоятельно: избегайте этого.

  • Вместо этого позвольте вызывающему передавать буфер, разрешите вызывающему указать размер буфера и скопируйте данные в этот буфер. Таким образом, вы можете использовать свою функцию из других модулей, которые не используют ту же кучу (другие языки программирования, другое время выполнения C ...)
  • Если вы по какой-либо причине не можете использовать такой интерфейс, укажите в документации к функции, что вызывающая сторона должна освободить возвращенный указатель после того, как это сделано с ним.

Если вы используете библиотечную функцию: ознакомьтесь с документацией.

  • Если в документации указано, что вы должны освободиться, сделайте это.
  • Если в документации говорится, что вам не нужно, это может быть какая-то глобальная функция очистки, которая должна вызываться для освобождения ресурсов модуля.

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

2 голосов
/ 02 декабря 2010

Да, каждый вызов malloc() должен соответствовать вызову free().

Чтобы ответить на ваши конкретные вопросы:

  1. Вы должны явно документировать свой API, сообщая пользователю, должен ли возвращаемый указатель быть free() 'd
  2. ОС освободит всю память, выделенную для процесса.
1 голос
/ 03 декабря 2010

Стандарт C не имеет понятия о системной среде вне выполнения одной программы, поэтому он не может указать, что происходит "после выхода из программы".В то же время нигде не требуется, чтобы память, полученная с помощью malloc, была или должна быть освобождена с помощью free до вызова exit или возврата из main, и я думаю, что вполне очевидно, чтоНамерение состоит в том, что выход без освобождения памяти вручную не оставит ресурсы связанными - очень похоже на то, как вызов exit без закрытия всех файлов, сначала автоматически закрывает их (включая их сброс).

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

  • Любой код библиотеки должен freeлюбая память, полученная исключительно для внутреннего использования, как можно скорее.
  • Библиотека, которая возвращает выделенные объекты вызывающей программе, должна всегда обеспечивать соответствующий вызов для освобождения этих объектов.
  • Библиотека, котораявыполняет любые распределения как часть глобальной инициализации (примечание: это очень плохой дизайн, но иногда неизбежный) должен обеспечитьДля приложения есть способ отменить эту инициализацию и освободить все, что было выделено.Это особенно важно, если библиотека может быть загружена динамически (даже в результате удовлетворения зависимостей другой динамически загружаемой библиотеки).

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

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

Всеоб этом во имя смешного правила «вы должны освободить все, что вы выделяете».

Для краткосрочных приложений это не так уж сложно, но вы часто можете упростить реализацию краткосрочных приложений.приложения, которые выполняют одну линейную задачу и завершают работу, если вы не удосуживаете освободить всю память, которую они выделяют.Подумайте о большинстве утилит командной строки Unix.Есть ли смысл писать циклы для sed, чтобы освободить все скомпилированные регулярные выражения перед выходом?Неужели время программистов не может быть потрачено на что-то более продуктивное?

0 голосов
/ 03 декабря 2010

Я бы не сказал, что все malloc должны быть освобождены, но я бы сказал, что независимо от того, как долго выполняется программа, должно быть ограниченное количество выделений (и общий размер), которые не будут быть освобожденным. Число не обязательно должно быть статической константой, но оно должно быть задано с точки зрения чего-то еще (например, эта программа обрабатывает виджеты; она будет выделять одну 64-байтовую структуру для каждого quizzix в самом большом виджете). Можно заранее не знать размер самого большого виджета, но если, например, кто-то знает, что временное хранилище, необходимое для обработки виджета, пропорционально квадрату его размера, можно с уверенностью предположить, что самый большой виджет будет достаточно маленьким, чтобы общий объем используемой памяти был довольно небольшим.

0 голосов
/ 02 декабря 2010

Давайте возьмем эти по одной точке за раз ...

  1. Если вы вернете char *, который, как вы знаете, был создан с помощью malloc, тогда да, это ваша ответственностьчтобы освободить это.Вы можете сделать это с помощью free(myCharPtr).

  2. Операционная система заберет память обратно, и она не будет потеряна навсегда, но технически нет никакой гарантии, что она будет возвращена правильно, когдаприложение умирает.Это зависит только от операционной системы.

0 голосов
/ 02 декабря 2010

1) Точно так же, как вы обычно освобождаете память, т.е.

p = func();
//...
free(p);

Хитрость заключается в том, чтобы убедиться, что вы всегда делаете это ...

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...