I think I've found a bug in the buffered io
library. The following code does work on
other systems but not on any version of
LINUX/GNU_C available to me now. (2.2.2d/jump4.1,
2.3.3/jump4.3.3 from SLS 1.01, 2.4.0/libc.4.4
from tsx-11)
The code below performs the following actions:
1) Open a file for writing and reading
2) Write two lines into the file ("1111.." and "2121..")
3) Flush buffers
4) Seek to the end of the first line
5) Flush buffers again
6) Write another two lines ("2222.." and "3333..")
This step should overwrite the second
line written by step 2) ("2121..")
and append another line.
7) Close file and terminate
Obviously, one would expect the file to
contain three lines after the program
has been executed:
1111111111 |
2222222222 |<--- Expected result
3333333333 |
But here comes what the file actually
looks like:
2222222222 |
3333333333 |<--- Real result
It seems that step 4 failed and set the
write pointer to 0 instead of 11 (=length
of each line). If you call "ftell" after
step 4) or 5), it returns the correct value: 11.
"ftell" returns a value of 11 again after
the next call of "fwrite". That fwrite
overwrites the FIRST line (position 0-10)
instead of the SECOND line (position 11-21).
I have found two by-passes for the problem:
A) Turn off buffering via "setvbuf(...,_IONBUF,...)"
B) Skip step 5 (fflush after fseek)
By-pass A) is inacceptable because I want
BUFFERED I/O to minimize execution time.
Solution B) works just in this very small
program. I am working on a quite complex
program which uses buffered I/O very
extensively. The program runs perfectly on
other platforms. It crashes almost immediately
on LINUX when I embed all "fseek"s by
"fflush"s. If I delete all "fflush"s (or
just the "fflush"s after the "fseek"s), the
program runs significantly better, but
sooner or later mysterious errors occur.
The program runs perfectly stable when
using "solution" A).
I just asked a friend of mine to verify
the problem to prevent me from posting
stupid things. He found out that there's
another solution for the problem:
C) Call setvbuf(..., _IOFBF, 129).
Any buffer size seems to be OK
which can be written as 2^n + 1 and
which is bigger than 9.
uli.
--------------------------------------------------------------------------- /*--CUT-HERE----CUT-HERE----CUT-HERE----CUT-HERE----CUT-HERE----CUT-HERE--* char line1[] = "1111111111\n"; int main(int argc, char *argv[]) f = fopen("tst.out", "wb+"); /* step 1 */
#include <stdio.h>
char line21[] = "2121212121\n";
char line22[] = "2222222222\n";
char line3[] = "3333333333\n";
/* char buffer[1000]; */
{
FILE *f;
int len = strlen(line1);
/*
** setvbuf(f, buffer, _IOFBF, 129);
** - or -
** setvbuf(f, NULL, _IONBF, 0);
*/
fwrite(line1, 1, len, f);
fwrite(line21, 1, len, f); /* step 2 */
fflush(f); /* step 3 */
fseek(f, 1*len, SEEK_SET); /* step 4 */
fflush(f); /* step 5 */
fwrite(line22, 1, len, f);
fwrite(line3, 1, len, f); /* step 6 */
fclose(f);
return(0); /* step 7 */
/*--CUT-HERE----CUT-HERE----CUT-HERE----CUT-HERE----CUT-HERE----CUT-HERE--*
--
---------------------------------------------------------------------------