I have learned setvbuf() function last week. But got a strange error.
The setvbuf function last argument is buffer size. When I set 1000, 2000, 3000, 4000, will be OK, but when I set it to 5000 or 7000, I will get a additional line.
Then, I try the same code in gcc 15.2, it is correct.
#include <stdio.h>
int main(void)
{
setvbuf(stdout, NULL, _IOFBF, 7000);
for (int i = 0; i < 20001; i++)
printf("%d\n", i);
return 0;
}1.png
Hi ander,
I could not reproduce this. With the setvbuf 1000, 5000, 7000, or not even use setvbuf it always ends the loop on 20000 . I just pasted your code in.
19998
19999
20000
Press any key to continue...
John Z
Quote from: John Z on March 09, 2026, 09:56:30 AMHi ander,
I could not reproduce this. With the setvbuf 1000, 5000, 7000, or not even use setvbuf it always ends the loop on 20000 . I just pasted your code in.
19998
19999
20000
Press any key to continue...
John Z
thank you for test.
I changed the number and try it again, and got different result, I got a new line "00".
Windows 11 Pro 25H2 simplified chinese. Only for chinese windows? I will try it on my laptop at home later
1.png
https://en.cppreference.com/w/c/io/setvbuf (https://en.cppreference.com/w/c/io/setvbuf)
buffer size should be at least multiple of 2
Quote from: TimoVJL on March 09, 2026, 11:54:49 AMhttps://en.cppreference.com/w/c/io/setvbuf (https://en.cppreference.com/w/c/io/setvbuf)
buffer size should be at least multiple of 2
I have read it last week. "the actual buffer size is usually rounded down to a multiple of 2". Just NOT use some bytes, so any number is OK.
I try it at home, my laptop. see picture.
1.png
simpler check
#include <stdio.h>
int main(void)
{
setvbuf(stdout, NULL, _IOFBF, 7000);
for (int i = 0; i <= 1351; i++)
printf("%d?\n", i);
return 0;
}
output:
...
1328?
329?
1330?
1331?
1332?
1333?
1334?
1335?
1336?
1337?
1338?
1339?
1340?
1341?
1342?
1343?
1344?
1345?
1346?
1347?
1348?
1349?
1350?
13511351?
'1157'
'1151158'
'1159'size: 7003
Test this - works for all buffer size setting I tried -
#include <stdio.h>
int main(void)
{ // all problems go away when next line is added
printf("test result");// initializes stdout I/O ?
setvbuf(stdout, NULL, _IOFBF, 7003);
for (int i = 0; i <= 1351; i++)
printf("%d?\n", i);
return 0;
}
Maybe because of this statement in the help file?
"The setvbuf function may be used only after the stream pointed to by stream has been associated with an open file and before any other operation (other than an unsuccessful call to setvbuf) is performed on the stream. "
I am thinking that printf is initializing the stdout stream before setvbuf is called on stdout so no problem.
John Z
how about check function setvbuf() error too ?
Great point! Checking the return shows my 'fix' only works because setvbuf fails return is -1! so no buffer at all.
When 'fix' is removed setvbuf passes return is 0 but then errors on 7003. In fact multiple errors in the return stream:
267? 0
268? 0
269?
270? 0
271? 0
-------
523? 0
524? 0
525?
526? 0
527? 0
-------
779? 0
780? 0
781?
782? 0
783? 0
-------
1011? 0
1012? 0
1013? 3? 0
1014? 0
1015? 0
-------
1239? 0
1240? 0
141? 0
1242? 0
1243? 0
Yikes something going on . . . . almost every 256th but some at 228
John Z
#include <stdio.h>
int main(void)
{
int size = 0;
if (setvbuf(stdout, NULL, _IOFBF, 5000))
fprintf(stdout, "setvbuf error\n");
else {
for (int i = 0; i <= 309; i++)
size += fprintf(stdout, "'%d'\n", i);
fprintf(stdout, "size: %d\n", size);
}
return 0;
}
'307'
'08'
'309'
size: 1750
The issue seems limited to the predefined streams.
Checked using stderr and the same issue exists.
Checked using a 'true' File *p_file stream and could not get it to fail. I also use setvbuf extensively in many places in other programs without issue so this makes sense.
To see if it is a 'speed' issue putting a delay loop between printf / fprintf steps might check that. For the most part the dropouts appear mostly in the same location, with minor variations which might be due to other activity on the system.
To be continued -
John Z
Update: Delay loop makes no difference.
for (loup = 0; loup < 8000000; loup++) // 8K to 8000k tested
{a = -a;}
Dropout (for want of a better word) is very consistent test after test happens in about the same location.
In the low-I/O C runtime function _write(), when operating in text mode (ANSI/UTF-16LE/UTF-8/...), there is a ~2kB buffer for LF to CRLF translation. When this buffer is full, the content is sent to the destination (console/file/...), the buffer cleared, and the translation resumed. When resuming the translation the first character was lost (in translation).
( The printf family is one path to the _write() function )
Thanks Pelle!
👍👍👍
John Z
Quote from: Pelle on March 15, 2026, 11:45:36 AMIn the low-I/O C runtime function _write(), when operating in text mode (ANSI/UTF-16LE/UTF-8/...), there is a ~2kB buffer for LF to CRLF translation. When this buffer is full, the content is sent to the destination (console/file/...), the buffer cleared, and the translation resumed. When resuming the translation the first character was lost (in translation).
( The printf family is one path to the _write() function )
Thank you, Pelle!