Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

Этот вопрос легче всего ответить, если мы его отменим:

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

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

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

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

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

Ответ 3

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

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

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

Ответ 4

Неплохая идея, если вы просто сохраните ее в своем собственном стиле.

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

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

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

char *obj;

my_new(&obj);

/* work on obj */

free(obj)

Изменить: сделано my_new() return int. Нет необходимости в двойных указателях в противном случае