Closing the FILE object.

From: Richard B. Johnson (root@chaos.analogic.com)
Date: Fri Jul 14 2000 - 12:25:06 EST


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)

NAME
       fclose - close a stream

SYNOPSIS
       #include <stdio.h>

       int fclose( FILE *stream);

DESCRIPTION
       The fclose function dissociates the named stream from its
       underlying file or set of functions. If the stream was
       being used for output, any buffered data is written first,
       using fflush(3).

RETURN VALUES
       Upon successful completion 0 is returned. Otherwise, EOF
       is returned and the global variable errno is set to indi-
       cate the error. In either case no further access to the
       stream is possible.

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.

Cheers,
Dick Johnson

Penguin : Linux version 2.2.15 on an i686 machine (797.90 BogoMips).

"Memory is like gasoline. You use it up when you are running. Of
course you get it all back when you reboot..."; Actual explanation
obtained from the Micro$oft help desk.

-
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