I'm learning system programming and when I run the following code
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
char buff[5];
setvbuf(stderr, buff, _IOFBF, 5);
for (int i = 1; i < 10; i++) {
fprintf(stderr, "%d", i);
}
_exit(0);
}
setvbuf
is imposing fully buffered policy on stderr
with a 5-byte sized buffer, so I expected to get 12345
but instead it prints 1234567
, why is that?
strace-ing the program shows that when compiled against glibc it first does a write of size 1, then a write of size 5, and finally a write of size 1:
$ strace -o /dev/stdout -e write,writev ./a.out 2>/dev/null
write(2, "1", 1) = 1
write(2, "23456", 5) = 5
write(2, "7", 1) = 1
With musl it does 7 writes of size 1:
$ strace -o /dev/stdout -e write,writev ./a.out 2>/dev/null
writev(2, [{iov_base="1", iov_len=1}, {iov_base=NULL, iov_len=0}], 2) = 1
writev(2, [{iov_base="2", iov_len=1}, {iov_base=NULL, iov_len=0}], 2) = 1
writev(2, [{iov_base="3", iov_len=1}, {iov_base=NULL, iov_len=0}], 2) = 1
writev(2, [{iov_base="4", iov_len=1}, {iov_base=NULL, iov_len=0}], 2) = 1
writev(2, [{iov_base="5", iov_len=1}, {iov_base=NULL, iov_len=0}], 2) = 1
writev(2, [{iov_base="6", iov_len=1}, {iov_base=NULL, iov_len=0}], 2) = 1
writev(2, [{iov_base="7", iov_len=1}, {iov_base=NULL, iov_len=0}], 2) = 1
writev(2, [{iov_base="8", iov_len=1}, {iov_base=NULL, iov_len=0}], 2) = 1
writev(2, [{iov_base="9", iov_len=1}, {iov_base=NULL, iov_len=0}], 2) = 1
+++ exited with 0 +++
So it's obvious that both C library implementations treat the size
argument of setvbuf(stream, buf, _IOFBF, size)
as a maximum, and they feel free to flush the buffer even before it's full.
AFAICS there doesn't seem to be anything in the standard against this interpretation.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.