Re: Closing the FILE object.

From: Jesse Pollard (pollard@tomcat.admin.navo.hpc.mil)
Date: Fri Jul 14 2000 - 15:23:06 EST


--------- Received message begins Here ---------

>
>
> This is in reference to the reported seg-faults when attempting to
> fclose() an invalid file pointer.
>
> The following shows that my current 'C' runtime library does not
> adhere to any known standard when referencing the FILE object during
> fclose(). This is gcc 2.7.2.3 (libc 5.3.12)
>
> According to existing Linux documentation, this should return
> EBADF. It should NOT seg-fault.
>
> #include <stdio.h>
> #include <malloc.h>
>
> int main ()
> {
> FILE *fp;
> fp = (FILE *)malloc(sizeof(FILE));/* Make sure the pointer is valid */
> fprintf(stderr, "%p\n", fp); /* Display valid address */
> fclose(fp);
> puts("It worked??"); /* Will not occur */
> return 0;
> }
>
>
> Script started on Fri Jul 14 12:50:27 2000
> $$$ man fclose
> FCLOSE(3) Linux Programmer's Manual FCLOSE(3)
[snip]
> ERRORS
> line 1 EBADF The argument stream is not an open stream.
> line 4
> The fclose function may also fail and set errno for any of
> the errors specified for the routines close(2) or
> fflush(3).
>
> SEE ALSO
> close(2), fflush(3), fopen(3), setbuf(3)
>
> STANDARDS
> The fclose function conforms to ANSI C3.159-1989 (``ANSI
> C'').
>
> BSD MANPAGE 29 November 1993 1
>
> line 19/66 (END)# exit
> exit
>
> Script done on Fri Jul 14 12:50:47 2000
>
>
> I reported a similar problem several years ago when I way trying to
> substitute during runtime, a FILE pointer obtained from a fopen() and
> the default FILE pointer(s) of stdin, stdout, stderr. In other words,
> if the program didn't have a terminal, stdout and stderr would go to
> a file.
>
> Because the FILE *object didn't work as a real pointer, I could not
> do:
> FILE *fp;
>
> fp = fopen("filename", "w");
> fflush(stdout);
> fflush(stderr);
> stdout = fp;
> stderr = fp;
>
> The next write to stdout would segfault. This behavior was never seen
> on any other Unix system, including Ultrix and Sun(s). In fact, the
> interplay of the FILE object was a feature of Unix 'C' programming.
>
> In the example above, I could have saved the original FILE *, and
> restored it later in the program. With Linux, you can't even compile
> such a program because the assignments will result in 'invalid lvalue'
> errors. This is because Linux libc's stdout is not a FILE * at all!
>
> This breaks compatability rules because, for instance fprintf() takes,
> as it's first parameter, a pointer of type FILE.
>
> So we have the case of fprintf(stderr, ...) compiling and working because
> stderr is a FILE pointer, but I can't make a legal assignment to it like
> any other FILE pointers.
>
> Go figure.

Yes, No and I understand.

AT&T System V had stdin/stdout/stderr defined as if the following were used:

const FILE *stdin = &STDIN;

static FILE STDIN = {....};

This ment that the default stdin/stdout.... were constants and could not
be modified.

HOWEVER, the release 2 manpage suggested that for portability all
I/O should go through a file pointer defined as:

FILE *input = stdin;

Then you COULD replace the default input by

   altinput = fopen(...);
   input = altinput;

The other note is that the manpage goes back to BSD in 1993. I don't think
the library functions implimenting fopen/fclose ... have remained the same.

At the time the man page was written the standard I/O library created the
file pointer from something like:

static FILE io[MAXFILECOUNT];
static int nextfile = 0;

....
FILE * fopen(char *path, char * mode)
{
        ...
        initialization for io[nextfile]
        io[nextfile] = open(path, intflags);
        ...
        if (io[nextfile] >= 0)
            return(&io[nextfile++]);
        return(NULL);
}

This allows the manpage to be correct, since the structure pointed to by
the FILE * variable is never deallocated. It is also NOT thread safe.

ALSO NOTE - this does not conflict with the "const FILE *stdin.." shown
earlier. stdin/stdout/stderr were not part of this array.

I don't think stdio library works that way anymore.

MAXFILECOUNT was 16 to 32 at the time, and multi-threaded I/O did not exist.

I think the manpage needs to be rewritten.

-------------------------------------------------------------------------
Jesse I Pollard, II
Email: pollard@navo.hpc.mil

Any opinions expressed are solely my own.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Jul 15 2000 - 21:00:20 EST