Почему malloc память в функции и освобождение ее снаружи - плохая идея?

если это плохая идея, как выделить память в функции?


person skydoor    schedule 31.03.2010    source источник
comment
Это может быть натяжкой для вашего вопроса, но идея похожа: выделение/освобождение памяти с помощью отдельных менеджеров памяти. Например, программа использует две библиотеки, которые статически связывают среду выполнения C. Программа размещает объект в одной библиотеке и освобождает его в другой. Это плохо. Если кто-то может лучше объяснить это, пожалуйста.   -  person Ioan    schedule 31.03.2010


Ответы (5)


Это не «плохая идея», а скорее «иногда плохая идея», что можно сказать о многих идеях в программировании.

Между прочим, выделение памяти внутри функции и освобождение ее снаружи может быть распространенным шаблоном проектирования. Рассмотреть возможность:

// hashtable is a typedef-ed pointer type
hashtable ht = hashtable_new();
// .. do something with hashtable
hashtable_free(ht);

ht был выделен в функции hashtable_new и освобожден вне ее, тем не менее, вы будете видеть этот шаблон снова и снова во многих хороших C-кодах.

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

person Eli Bendersky    schedule 31.03.2010

На этот вопрос легче всего ответить, если мы изменим его:

  • Почему может быть хорошей идеей, если каждый объект mallocd в функции также freed в той же функции?

Ответ таков: утечек памяти или оборванных указателей не будет, и этот ценный результат достигается без участия какой-либо другой функции. В результате легче получить правильный код, а функция имеет простой интерфейс.

А что, если функция вызывает malloc, но не free? Затем должны быть правила о том, кто обязан освобождать память, когда это разрешено и когда это требуется. Эти правила становятся частью интерфейса функции, и любой, кто вызывает функцию, должен либо убедиться, что правила или соблюдаются, либо, возможно, наложить аналогичные правила на его вызывающего(ых), и скоро. Явное управление памятью усложняет интерфейсы, и чем сложнее интерфейсы, тем легче сделать ошибку, которая приведет к ошибке памяти, а в C ошибка памяти может привести к сбою программы.

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

(Один из более простых случаев — это когда объект выделяется во время выполнения, но ему разрешено жить вечно. Но вы должны ограничить количество таких объектов, иначе у вас закончится место.)

person Norman Ramsey    schedule 31.03.2010

Это неплохая идея, если вы просто будете придерживаться своего собственного стиля.

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

void my_new(char **obj) {
    *obj = malloc(somesize);
}

а затем вызовите это из своей функции следующим образом:

char *obj;

my_new(&obj);

/* work on obj */

free(obj)
person joveha    schedule 31.03.2010

Не обязательно плохо выделять память в функции. Вы просто должны убедиться, что очистить его должным образом.

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

Просто будьте осторожны с вашим дизайном. Сопоставляйте malloc с free каждый раз, и утечек памяти не будет.

person duffymo    schedule 31.03.2010

Существуют определенные шаблоны для управления памятью:

  1. выделить память внутри функции, освободить ее снаружи, когда она переживет положенное время
  2. чтобы удерживать указатель в функции, где вызывается malloc, и освобождать его после истечения срока его действия, как сказал joveha.

Помните о согласованности, иначе это легко приведет к утечке памяти или оборванным указателям.

person YoungJeXu    schedule 01.03.2018