Search code examples
cglibc

setvbuf not changing buffer size?


I have the following toy code to test out I/O buffering on fread, and I'm getting results that I didn't expect:

#include <stdio.h>
#include <stdio_ext.h>

int main()
{
    FILE *fp;
    char buff[255];
    fp = fopen("/home/install.sh", "r");
    int result = setvbuf(fp, NULL, _IOFBF, 700); // set buffering size to some arbitrary value, say 700
    printf("Result of setting buffer: %d\n", result ); // "Result of setting buffer: 0"
    printf("Buffer size: %zd\n", __fbufsize(fp) ); // "Buffer size: 4096"


    fread(buff, 255, 1, fp);
    printf("%s\n", buff ); // prints 255 bytes as I would expect

}

From above, it seems like the setvbuf call was successful as it returned 0, however the buffer size stays at 4096. Moreover, I tried printing out BUFSIZ and it says 8192. Running strace does show the underlying read call as being 4096 bytes. Turning off buffering seems to work fine, as buffer size gets set to 1.

Moreover, I don't understand why BUFSIZ (8192) is not the same as the default value of these reads (4096).

I tried many different values for the buffer size but to no avail.

I am running ldd (Ubuntu GLIBC 2.27-3ubuntu1) 2.27


Solution

  • setvbuf not changing buffer size?

    Glibc setvbuf implementation just ignores the size argument when mode == _IOFBF and buff == NULL. Which is fine - characteristics of buffering modes are implementation defined. And __fbufsize is a nonstandard extensions. Generally you shouldn't depend on the buffering of the underlying FILE.

    I don't understand why BUFSIZ (8192) is not the same as the default value of these reads (4096).

    Glibc does mmap the file. Because of mmap the size get's rounded to page size.