Итак, я покопался в том, как реализована stdio часть libc, и натолкнулся на другой вопрос. Глядя на man setvbuf
я вижу следующее:
Когда происходит первая операция ввода-вывода
вызывается файл malloc (3), а
буфер получен.
Это имеет смысл, ваша программа не должна иметь malloc
в ней для ввода / вывода, если вы фактически не используете ее. Моя внутренняя реакция на это заключается в том, что libc уберет здесь свой собственный беспорядок. Я могу только предположить, что это происходит, потому что valgrind не сообщает об утечках памяти (они, конечно, могли бы сделать что-то грязное и не выделять это напрямую через malloc
... но мы будем предполагать, что сейчас оно буквально использует malloc
).
Но , вы также можете указать свой собственный буфер ...
int main() {
char *p = malloc(100);
setvbuf(stdio, p, _IOFBF, 100);
puts("hello world");
}
О нет, утечка памяти! Валгринд подтверждает это. Поэтому кажется, что всякий раз, когда stdio выделяет буфер самостоятельно, он автоматически удаляется (самое позднее при выходе из программы, но, возможно, при закрытии потока). Но если вы укажете буфер явно, вы должны очистить его самостоятельно.
Хотя есть одна загвоздка. На странице руководства также написано:
Вы должны убедиться, что пространство, которое
Буф указывает на все еще существует к тому времени
поток закрыт, что тоже бывает
при завершении программы. Например,
следующее недействительно:
Теперь это становится интересным для стандартных потоков. Как правильно очистить выделенный вручную буфер, поскольку они закрываются при завершении программы? Я мог бы представить себе «очистить это, когда я закрываю флаг» внутри структуры файла, но это становится проблематичным, потому что, если я читаю это правильно, делая что-то вроде этого:
setvbuf(stdout, 0, _IOFBF, 0);
printf("hello ");
setvbuf(stdout, 0, _IOLBF, 0);
printf("world\n");
вызовет 2 выделения стандартной библиотекой из-за этого предложения:
Если аргумент buf равен NULL, только
режим влияет; новый буфер будет
выделяется при следующем чтении или записи
работа.
РЕДАКТИРОВАТЬ: дополнение к моему вопросу. Поскольку ясно, что я должен free
любые буферы, которые я передаю setvbuf
, если я действительно использую его на stdout
, есть ли практический способ free
? Он должен жить до конца программы. Лучшее, что я могу придумать, - это fclose(stdout)
, затем освободить его или использовать статический буфер, как упоминали некоторые люди. Я спрашиваю, потому что это кажется неуклюжим дизайнерским решением.