если это - плохая идея, как выделить память в функции?
Это не «плохая идея», а скорее «иногда плохая идея», что можно сказать о многих идеях в программировании.
Между прочим, распределение памяти внутри функции и ее освобождение снаружи может быть обычным шаблоном проектирования. Подумайте:
// hashtable is a typedef-ed pointer type
hashtable ht = hashtable_new();
// .. do something with hashtable
hashtable_free(ht);
ht
был выделен в функции hashtable_new
и выпущен вне ее, но вы снова и снова будете видеть этот шаблон во многих хороших кодах C.
Однако он показывает, как одна и та же логическая единица (ADT хеш-таблицы) заботится о выделении и освобождении. В этом есть большой смысл - потому что тот, кто знает, как выделить, лучше знает, как освободить. Размещение и освобождение в различных логических единицах чаще всего является плохой идеей.
Это неплохая идея, если вы просто будете придерживаться своего собственного стиля.
Хорошим подходом является передача выделенной памяти вызывающей стороне, которая затем может освободить ее по завершении работы. Что-то вроде этого:
void my_new(char **obj) {
*obj = malloc(somesize);
}
и затем вызвать это из вашей функции так:
char *obj;
my_new(&obj);
/* work on obj */
free(obj)
Выделение памяти в функции не обязательно плохая идея. Вы просто должны убедиться, что очистили его должным образом.
Проблема в том, что вы можете потерять возможность делать это после выхода из области видимости функции.
Просто будьте осторожны со своим дизайном. Сопоставляйте malloc с free каждый раз, и у вас не будет утечек памяти.
На этот вопрос проще всего ответить, если перевернуть его:
malloc
'd в функции также свободен
d в та же функция? Ответ таков: не будет утечек памяти или зависших указателей , и этот ценный результат достигается без взаимодействия с какой-либо другой функцией . В результате код становится проще, а функция имеет простой интерфейс.
А что, если функция вызывает malloc
, но не free
? Затем должны быть правила о том, кто обязан освобождать память, когда это разрешено, а когда это требуется . Эти правила становятся частью интерфейса функции , и любой, вызывающий функцию, должен либо обеспечить соблюдение правил, либо, возможно, наложить аналогичные правила на своих вызывающих лиц и т. Д. . Явное управление памятью усложняет интерфейсы , и чем сложнее интерфейсы, тем легче совершить ошибку, которая приведет к ошибке памяти, а в C ошибка памяти может привести к сбою вашей программы.
К сожалению, иногда необходимо иметь объект, который (a) должен быть выделен во время выполнения и (b) должен пережить активацию функции, которая его выделяет. В таких случаях, даже если кажется, что это может быть плохой идеей, у нас нет другого выбора, кроме как выполнить выделение, усложнить интерфейс и потребовать от вызывающего объекта правильно управлять объектом.
(Один из более простых случаев - когда объект выделяется во время выполнения, но ему разрешено жить вечно. Но вы должны ограничить количество таких объектов, иначе у вас закончится место.)
{{1 }}