Освобождение памяти, возвращенной из функций C

Используйте метод Trim.

5
задан Kai 26 May 2009 в 18:40
поделиться

10 ответов

Вы никогда не должны освобождать файл - fclose обрабатывает освобождение ресурсов должным образом. Как правило, только свободные указатели, которые были выделены непосредственно malloc. Большинство других указателей будут иметь свои собственные функции очистки ресурсов.

При этом, что касается вашего первоначального вопроса:

Я считаю, что предоставление функции деструктора обычно лучше по трем причинам.

1) Там Во многих случаях бесплатное использование неприемлемо, и это может быть неочевидно для вашего конечного пользователя. FILE * - хороший тому пример - вы не должны вызывать free (f); выше ...

2) Если вы используете это в DLL, в зависимости от времени выполнения, имея инкапсулированная бесплатная функциональность может обойти множество мелких ошибок из-за смешивания сред выполнения, особенно на платформе Windows. Попытка использовать DLL, скомпилированную в VS2005 из VS2008, может вызвать проблемы, если вы случайно освободите память в коде одной платформы, которая была выделена в другой. Наличие функции-оболочки для управления памятью позволяет обойти эту важную проблему.

3) Многие функции C API работают таким образом - например, FILE * с использованием fopen / fclose. Это не удивит пользователя вашей библиотеки.

10
ответ дан 18 December 2019 в 05:40
поделиться

Лучший вариант выделения и освобождения памяти - сделать это симметрично. т.е. если вызывающий абонент выделяет память, позвольте вызывающему абоненту освободить ее. Если ваш API выделяет память (вызываемый объект), ваш API должен освободить его.

Пример выделения / освобождения вызывающего объекта:

int * mymem = (int *)malloc(20 * sizeof(int));
...
a_func_to_call(mymem);
...
free(mymem);

Пример выделения / освобождения вызываемого объекта:

FILE* f = fopen("blah", "w"); // allocs a FILE struct
fclose(f); // The implementation of fclose() will do what's necessary to 
           // free resources and if it chooses to deallocate any memory
           // previously allocated
14
ответ дан 18 December 2019 в 05:40
поделиться

Вы не можете освободить ФАЙЛ * это не было выделено malloc.
Поскольку вы не отвечали за его распределение, вам не следует его освобождать.

5
ответ дан 18 December 2019 в 05:40
поделиться

FILE * f - это указатель на объект FILE, который используется для идентификации потока во всех дальнейших операциях с файлом. Вы не должны использовать free (f) , поскольку память не выделяется функцией malloc ().

fclose достаточно, чтобы закрыть файл, связанный с потоком.

] По поводу вашего вопроса о предоставлении функции деструктора для освобождения памяти: Я считаю, что уместно предоставить функцию типа деструктора, если функция делает больше, чем освобождает память.

wrapperFree(Pointer* p)
{
 //do some additional work [ other cleanup operations ]
 free(p);
}

Кроме того, для WrapperFree необходимо предоставить WrapperAllocate.

В противном случае, я думаю, что для каждого malloc () явно вызовите free () .

2
ответ дан 18 December 2019 в 05:40
поделиться

fopen возвращает указатель на структуру библиотеки C, управляемую изнутри FILE , которая освобождается (не обязательно бесплатно d) при вызове fclose .

0
ответ дан 18 December 2019 в 05:40
поделиться

I думаю, вы имели в виду malloc () , а не fopen () . malloc () выделяет память и возвращает адрес выделенной памяти. Это должно быть выпущено с помощью вызова free () .

0
ответ дан 18 December 2019 в 05:40
поделиться

Как говорит mgb, нет необходимости в free () ФАЙЛ * . Но в типичном использовании есть вызовы библиотеки и ваш собственный код, который выделяет память и заставляет вас отвечать. Вот несколько общих рекомендаций:

  • Создайте функцию «деструктор», когда что-то должно произойти, помимо освобождения памяти. Пример FILE * - прекрасный пример: он должен работать как с самим файлом, так и с памятью.
  • Используйте голый free () , когда это всего лишь кусок объем памяти. Все остальное является излишним.
0
ответ дан 18 December 2019 в 05:40
поделиться

Нет лучшей практики без контекста ...

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

Функция open / allocate должна возвращать непрозрачный дескриптор какого-либо типа, который закрывается / освобождается функцией закрытия.

FILE * можно рассматривать как такой непрозрачный дескриптор.

0
ответ дан 18 December 2019 в 05:40
поделиться

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

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

0
ответ дан 18 December 2019 в 05:40
поделиться

Мне нравятся не только функции деструктора, но и соглашение Дейва Хэнсона, которое принимает адрес указателя и обнуляет указатель при освобождении памяти:

Thing_T *Thing_new(void);
void Thing_dispose(Thing_T **p);   // free *p and set *p = NULL
0
ответ дан 18 December 2019 в 05:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: