0

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

int myfunction(char *s) 

В этой функции, строка, на которую указывает s получает манипулируют, а значение return является кодом ошибки.

Предположим, что указатель прошел уже на malloc() памяти. Является ли моя ответственность (создание библиотеки) освобождать эту память в верхней части функции, или это ошибка пользователя библиотеки за то, что она не знает, что эта функция будет звонить на malloc() или связана с этим и устанавливает s вместо этого?

+0

Я не понимаю, что происходит. Кто вызывает 'malloc()'? Вы? Пользователь? Почему вы хотите освободить то, что пользователь, по-видимому, хочет потреблять позже? –

+0

"эта функция будет делать вызов для malloc() или связанных и устанавливать s вместо этого там?" - пахнет недоразумением. Установка указателя * внутри * функция ** не будет изменять ее, и это означает, что ваша * функция будет утечка памяти. Вам даже не нужно ничего malloc, если 's' является действительным при передаче вашей функции (как это определенно должно быть). –

+0

Wel .. обычно. Это зависит от того, будет ли функция принимать участие в переданной строке, например. путем очередности указателя на внутренний поток). Тем не менее, вы правы - указатель передается по значению, и библиотека не может магически изменить его. –

ответ

2

Обычный договор - это лицо, делающее malloc, является лицом, выполняющим free.

Также учтите, что данные, на которые указывает, возможно, не были malloc 'в первую очередь. Может быть в стеке

+0

@ KerrekSB - Плохой язык с моей стороны –

1

Если ваше намерение не изменить строку, она должна быть объявлена ​​const:

int myfunction(const char *s); 

Тогда стало ясно, что myfunction() не возьмет на себя ответственность и попытаться освободить строку (вам не может вызвать free() с указателем const), который является типичным подходом.

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

+1

Если он действительно принадлежит владельцу, в документации должно быть четко указано, что буфер/строка должна быть динамически распределена, и вызывающий абонент не должен ее освобождать. –

+0

Это просто ложный отрицательный (или положительный, не уверенный) отказ от передачи права собственности, поскольку отсутствие const не означает обратного. И на самом деле это очень редкий случай, когда вы это делаете - интерфейсы не должны работать с нединамическими строками (и объектами вообще). Создание динамической копии обычно является работой потребителя, а не производителем. – user3125367

+0

Проблема с этим, ну, ему нужна операция копирования, которой можно избежать. Если вы собрали, уже по большой цене, буфер 10 МБ, а не копирование, это очень хороший выигрыш. То, что может показаться «правильным», - это, по сути, действительно плохая идея. –

0

Хорошо, если мы посмотрим на различные apis, тогда мы получим представление. Например, strdup(), где мы передаем const char *s в качестве аргумента, strdup() берет на себя ответственность за выделение памяти. С другой стороны, вы также найдете примеры, где функции обычно не несут ответственность за выделение буфера i.e fgets() (есть еще много). Доступны также функции, которые позволяют использовать, например, getline(). От человека странице getline():

If *lineptr is NULL, then getline() will allocate a buffer for storing the line 
    ,which should be freed by the user program. (In this case, the value in *n is 
    ignored.) 

    Alternatively, before calling getline(), *lineptr can contain a pointer to a 
    malloc(3)-allocated buffer *n bytes in size. 

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

Смежные вопросы