setvbuf() — параметр размера, когда buf равен НУЛЮ

#c #glibc #stdio

#c #glibc #стандартный формат

Вопрос:

Кажется, что когда я запускаю следующий код:

 #include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv)
{
    int i=0;

    setvbuf(stdout, NULL, _IOLBF,0);

    while (1)
            printf("%d ",i  );

    return 0;
}
  

он печатает порциями по 1024 символа, независимо от размера, который я определяю для setvbuf().
Вопрос в том, влияет ли как-то в этом случае размер и откуда берется определение для 1024 символов.

Ответ №1:

Я не знаю, как вы определили, 1024 но это, вероятно BUFSIZ . BUFSIZ определяется в stdio.h .

Если buf равно нулю, то библиотека stdio автоматически выделяет буфер для использования с потоком (если мы не выбираем небуферизованный ввод-вывод).

Редактировать

Вот что glibc говорит:

Макрос: int BUFSIZ Значение этого макроса является целочисленным постоянным выражением, которое удобно использовать в качестве аргумента размера для setvbuf. Это значение гарантированно должно быть не менее 256.

Значение BUFSIZ выбирается в каждой системе таким образом, чтобы сделать потоковый ввод-вывод эффективным. Поэтому хорошей идеей будет использовать BUFSIZ в качестве размера буфера при вызове setvbuf.

ПРАВКА 2

@larsmans прав. Я посмотрел, как setvbuf это реализовано, и он игнорирует вызов при запросе буферизации строки и представлении буфера с НУЛЕВЫМ значением. Теперь stdout это не обычный файл, он прикреплен к терминалу. Итак, переходим к pixelbeat

  • Размер буфера напрямую влияет только на режим буферизации
  • Размер по умолчанию, как и в ядре, основан на размере страницы (4096 байт в моей системе)
  • если stdin / stdout подключены к терминалу, то размер по умолчанию = 1024;
    в противном случае размер = 4096

Комментарии:

1. Маловероятно; в моей системе Linux / glibc BUFSIZ == 8192 .

2. @larsmans У меня тоже; но я только что запустил его в VS 2008 и там BUFSIZ == 512 . Кроме того, я все еще не знаю, так ли это на самом деле 1024 .

Ответ №2:

В соответствии с (черновиком) Стандарт C,

Если buf указатель не равен нулю, массив, на который он указывает, может использоваться вместо буфера, выделенного setvbuf функцией, а аргумент size указывает размер массива; в противном случае, size может определять размер буфера, выделенного setvbuf функцией. [Выделено мной.]

Итак, предполагая, что вы измерили правильно, похоже, что Glibc может делать все, что ему заблагорассудится, когда buf равно нулю, и это дает вам буфер размером 1 КБ. Поскольку вы никогда не вводите новую строку, буферизация строк не влияет, и поведение аналогично полной буферизации.

Ответ №3:

Размер, вероятно, не оказывает большого влияния на указатель буфера с нулевым значением.

Однако вы по-прежнему запрашиваете буферизованный вывод с помощью _IOLBF Try _IONBF вместо этого.

http://en.wikipedia.org/wiki/Setvbuf