Undefined side-effect of setvbuf?

K

Keith Doyle

I'm curious if setvbuf behavior is known to be undefined with regards
to effects it may have on the file pointer. I've found that the
following code works different on AIX 4.3.3 xlc and FreeBSD gcc 2.95.2
19990314 than it does on SCO 5.0.4 cc or Linux gcc egcs-1.1.2 19991024.
This is a bit curious as here's a gcc example that works one way and
one that works the other, and I would think the relevant code is in
libc/glibc.

This is what is going on. If you fopen a file, read a small amount
of data from it and then fseek(fp,0,SEEK_SET), a subsequent setvbuf
to some buffer value (non-0) causes the filepointer returned by
ftell(fp) to be nonzero in the AIX and FreeBSD cases listed above,
and it is zero in the other cases. If you don't do the fread and
fseek first, the filepointer is zero in all cases.

I couldn't find any mention of this behavior, though the particular
conditions here are probably a little unusual. The reason I'm
reading the file first is to check the type of file (by looking at
a header) and decide whether or not to setvbuf based on that.
There are several easy workarounds, I could close and reopen the
file, or simply fseek(fp,0,SEEK_SET) AFTER the setvbuf. But I was
curious as to whether there is any mention anywhere about setvbuf
effect on the filepointer, as I wasn't able to find any...

--

Keith Doyle
(e-mail address removed)

====================== sample code =========================
/*
run the resultant binary with the name of a small file
(a couple hundred bytes long) as a parameter. This program
will fopen the file, read 16 bytes, fseek to 0, then do a
setvbuf with a buffer size of 16384. ftell is then used to
read the filepointer and report its value if it is non zero.
*/
#include <stdio.h>
#include <errno.h>

unsigned char dat[16];
char buf[16394];

int
main(int argc,char **argv)
{
int n,p;
FILE *fp;

if (argv[1][0])
{
fp = fopen(argv[1],"r");
if (!fp)
{
fprintf(stderr,"Can't open %s\n",argv[1]);
exit(1);
}

fread(dat,1,16,fp); /* remove these and they all act the same*/
fseek(fp,0,SEEK_SET);

errno = 0;
n = setvbuf(fp,buf,_IOFBF,16384);
p = ftell(fp);
if (p)
{
printf("setvbuf changed file position to %d\n",p);
}
if (n < 0)
printf("setvbuf returned %d, errno=%d\n",n,errno);
else
printf("setvbuf returned %d\n",n);
exit(0);
} else {
fprintf(stderr,"Usage: bufbug <filename>\n");
exit(1);
}
}
===================end included code========================
 
L

lawrence.jones

Keith Doyle said:
This is what is going on. If you fopen a file, read a small amount
of data from it and then fseek(fp,0,SEEK_SET), a subsequent setvbuf
to some buffer value (non-0) causes the filepointer returned by
ftell(fp) to be nonzero in the AIX and FreeBSD cases listed above,
and it is zero in the other cases. If you don't do the fread and
fseek first, the filepointer is zero in all cases.

The C Standard says you're not allowed to perform other operations on
the stream before calling setvbuf. You're violating that, so you get
undefined behavior.

-Larry Jones

I suppose if I had two X chromosomes, I'd feel hostile too. -- Calvin
 
A

Alan Balmer

This is what is going on. If you fopen a file, read a small amount
of data from it and then fseek(fp,0,SEEK_SET), a subsequent setvbuf

Can't do that. setvbuf must be called after the file is opened, but
before any other operations on the file.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Help with EXT3 Filesystem work 1
Binary File I/O 11
A Question of Style 51
URGENT 1
fseek 17
How to do Lexical analysis for c/c++ source file? 0
Question about change of "fp" in function "fseek"and "ftell" 3
error 28

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top