Нужно ли освобождать нединамическую структуру с элементами указателя?

#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, когда-либо написанный: все категории, все языки. Единственное, что в нем хорошо,-это то, что все недостатки хорошо известны