#c #pointers
Вопрос:
Я поискал это, но не нашел ни одного с моим конкретным случаем. Если у меня есть такая структура, как эта:
typedef struct test {
void *data;
int *something;
} Test;
И тогда у меня есть функция, которая делает Test
Test new(void *data, int *something) {
Test new;
new.data = data;
new.something = something;
return new;
}
Тогда, если я вызову функцию, понадобятся ли мне свободные элементы Test
или их члены? Также изменился бы этот ответ, если бы я использовал malloc для участников data
или something
?
Комментарии:
1. Простое правило таково: для каждого
malloc
вам нужен одинfree
. В вашем коде его нетmalloc
, так что вам ничего не нужноfree
2. @Gerhardh
realloc
отсутствует в вашем списке3. И
strdup
если это будет добавлено в стандарт.4. Не связано: Ваша функция кажется довольно бесполезной, и ее название вводит в заблуждение. Чтобы использовать его, нужно сделать:
Test t = new(data, something);
но без функции вы можете это сделатьTest t = {data, something};
, поэтому ваша функция на самом деле не очень помогает. Язык C уже содержит эту функциональность, поэтому нет необходимости в написании функции.
Ответ №1:
Некоторые эмпирические правила:
- Для каждого
malloc
(calloc
/strdup
и т.д.) должно быть соответствующееfree()
. Еслиmalloc
нигде нет, то не может бытьfree
и того, и другого. - При разумном проектировании программы ответственность за очистку также лежит на модуле, который выделил что-то
malloc
для обработки очистки.Поэтому, если какая-то библиотека использует malloc внутри, вы должны ожидать, что для этой цели вы найдете функцию «удалить»/»уничтожить»/»очистить»/»освободить»/»закрыть» и т. Д.
Аналогично, возврат указателей на динамически выделяемую память и ожидание, что кто-то другой очистит их, — это плохой дизайн программы и то, как именно вы создаете утечки памяти во многих приложениях, использующих вашу библиотеку. Из многолетнего опыта работы с языком Си мы знаем, что такие плохо разработанные функции, как
getline
, например, многократно виноваты в утечках памяти.
Комментарии:
1. Вы также считаете
realloc
, что они плохо спроектированы?2. @IanAbbott Как правило, назначение
*alloc
функций состоит в выделении памяти и ничего больше, поэтому они являются особыми случаями. Но ну даrealloc
, у него проблемный дизайн, но по другой причине: не очень очевидно, что делать, когда он выходит из строя. Что-то подобноеbool realloc(void**, size_t);
могло бы иметь больше смысла при условии, что оно не касается переданного указателя в случае сбоя распределения.3. Это
void**
было бы сложно использовать, когда указатель хранится в чем-то, отличном от объекта, тем болееvoid*
, что он обычно используется для перераспределения динамических массивов некоторого полного типа объектов.4. Существует также пословица: «Хороший рабочий никогда не винит свои инструменты». (Но это требует обновления, чтобы быть больше ПК!)
5. @IanAbbott, почему бы и нет, если мой инструмент-тачка с квадратным колесом, а все остальные используют круглые колеса, в значительной степени с момента изобретения колеса (приличная система типов). Вместо этого, как насчет «хороший инженер всегда ставит под сомнение требования». Мы не используем компьютеры 50-летней давности, на которых работают процессоры 50-летней давности на источниках питания 50-летней давности. Так зачем же использовать 50-летний (отсутствие) дизайн API и отсутствие разумной системы типов? Стандартная библиотека C в целом просто ужасна, возможно, самый худший API, когда-либо написанный: все категории, все языки. Единственное, что в нем хорошо,-это то, что все недостатки хорошо известны