кто буфер setvbuf free?

Таким образом, я рыл в то, как stdio часть libc реализована, и я столкнулся с другим вопросом. Взгляд на man setvbuf Я вижу следующее:

Когда первая операция ввода-вывода происходит на файле, malloc (3) назван, и буфер получен.

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

Но, можно указать собственный буфер также...

int main() {
    char *p = malloc(100);
    setvbuf(stdio, p, _IOFBF, 100);
    puts("hello world");
}

О нет, утечка памяти! valgrind подтверждает это. Таким образом, кажется, что каждый раз, когда stdio выделяет буфер самостоятельно, он будет удален автоматически (самое позднее на выходе программы, но возможно на потоке близко). Но если Вы указываете буфер явно, затем необходимо убрать его сами.

Существует выгода все же. В странице справочника также говорится это:

Необходимо удостовериться, что пространство, на которое указывает buf все еще, существует к тому времени, когда поток закрывается, который также происходит при завершении программы. Например, следующее недопустимо:

Теперь это становится интересным для стандартных потоков. Как можно было бы правильно очистить вручную выделенный буфер для них, так как они закрываются в завершении программы? Я мог вообразить, "очищают это, когда я закрываю флаг" в структуре файла, но это становится волосатым потому что, если я считал это право, делающее что-то вроде этого:

setvbuf(stdout, 0, _IOFBF, 0);
printf("hello ");
setvbuf(stdout, 0, _IOLBF, 0);
printf("world\n");

вызвал бы 2 выделения стандартной библиотекой из-за этого предложения:

Если аргумент buf является НУЛЕВЫМ, только режим затронут; новый буфер будет выделен на следующей операции чтения или операции записи.

Править: приложение к моему вопросу. Так как ясно, что я должен free любые буферы я передаю setvbuf, если я действительно на самом деле использую его на stdout есть ли любой практический путь к free это? Это должно жить для программирования конца. Лучшее, о котором я могу думать, к fclose(stdout) затем освободите его или используйте статический буфер, как некоторые люди упомянули. Я спрашиваю, потому что это действительно походит на неловкое проектное решение.

7
задан Evan Teran 8 February 2015 в 17:22
поделиться

3 ответа

Также из справочной страницы (по крайней мере, в моей системе):

Если buf не равен NULL, это Ответственность вызывающего абонента освободить (3) этот буфер после закрытия потока.

То есть вы его распределили, вы освободили.

Перед выходом вы можете закрыть потоки самостоятельно, что позволит вам освободить буфер. В качестве альтернативы вы можете очистить потоки и снова вызвать setvbuf с аргументом буфера NULL , чтобы переключиться обратно на управляемый библиотекой буфер или небуферизованный ввод-вывод.

3
ответ дан 7 December 2019 в 07:42
поделиться

По крайней мере, в соответствии со стандартом C ваш последний сценарий просто не разрешен: «Функция setvbuf может использоваться только после того, как поток, на который указывает поток, был связан с открытым файлом и перед любой другой операцией (кроме неудачный вызов setvbuf) выполняется в потоке ". (C99, §7.19.5.6 / 2).

Что касается того, когда освобождать память в более простых случаях, можно вызвать atexit () , чтобы зарегистрировать обратный вызов, который освободит память после выхода из main () , но до того, как управление будет возвращено ОС.

3
ответ дан 7 December 2019 в 07:42
поделиться

Вы можете закрыть stdin , stdout и stderr явно (с помощью fclose () ).

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

1
ответ дан 7 December 2019 в 07:42
поделиться
Другие вопросы по тегам:

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