Когда сторонняя функция C возвращает указатель, вы должны освободить ее самостоятельно? - PullRequest
7 голосов
/ 06 сентября 2010

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

Например, функция inet_ntoa возвращает char*, скорее всего, из ниоткуда, но на странице руководства не указано, как она была выделена. Вместо этого я использовал inet_ntop, потому что, по крайней мере, я знал, откуда пришло назначение.

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

Ответы [ 5 ]

12 голосов
/ 06 сентября 2010

Вы должны прочитать документацию, другого пути нет.Моя справочная страница для inet_ntoa гласит:

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

Так что в этом случае вы не должныпопытка освободить возвращенный указатель.

3 голосов
/ 06 сентября 2010

Там действительно нет стандартного правила.Некоторые функции требуют, чтобы вы передали указатель, и они заполняют данные в это пространство (например, sprintf).Другие возвращают адрес области статических данных (например, многие функции в <time.h>).Другие по-прежнему выделяют память при необходимости (например, setvbuf).

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

1 голос
/ 06 сентября 2010

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

со справочной страницы inet_ntoa:

Функция inet_ntoa () преобразует Адрес интернет-хоста в, указан в сетевой порядок байтов, в строку в Десятично-десятичная запись IPv4. строка возвращается в статически выделенный буфер, который последующий звонки будут перезаписывать.

0 голосов
/ 06 сентября 2010

Я думаю, что ваша идея, что "многие" функции в POSIX возвращают указатели таким образом, ошибочна.Ваш пример, inet_ntoa это не в POSIX и был намеренно исключен из-за того, что он устарел и не работает.

Количество стандартных функций, которые возвращают указатели на выделенную память, на самом деле довольно мало, и большинствоиз тех, которые предоставляют специальную дополнительную функцию, которую вы должны использовать для освобождения памяти (например, fopen и fclose, getaddrinfo и freeaddrinfo или regcomp и regfree),Простой вызов free для возвращенного указателя был бы очень плохим;в лучшем случае вы столкнетесь с серьезными утечками памяти, а в худшем случае это может привести к неожиданным сбоям (например, если библиотека хранит объекты, выделенные ей в связанном списке).системной библиотеки или сторонней библиотеки, она должна документировать ожидаемое использование любых указателей, которые она возвращает (и необходимо ли / как их освобождать).Для стандартных функций лучшим справочником по этому вопросу является сам POSIX .Вы также можете проверить справочные страницы для вашей конкретной системы.Если код является частью сторонней библиотеки, он должен поставляться с документацией (возможно, на страницах руководства, в заголовочных файлах или во всеобъемлющем документе по использованию библиотеки).Хорошо написанная библиотека будет предоставлять специальные функции для освобождения объектов, которые она выделяет, чтобы избежать введения зависимостей от того, как (в настоящее время) она реализована в коде, использующем библиотеку.

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

0 голосов
/ 06 сентября 2010

По крайней мере, на моем компьютере (Mac OS X 10.6) последнее предложение man-страницы под BUGS:

Строка, возвращаемая inet_ntoa (), находится в статической области памяти.

...