Issue
I'm trying to use the c library function fputc from stdio.h
I'm assuming it should work according to the spec at https://linux.die.net/man/3/fputc
Specifically, the parts that are of interest are:
- fputc() writes the character c, cast to an unsigned char, to stream.
- fputc(), putc() and putchar() return the character written as an unsigned char cast to an int or EOF on error.
Based on this information, I assume that if fputc successfully writes the character to the stream provided, I should receive a return value equal to the character written, and if it fails to write to the stream, I should get the value of EOF.
Here is my code:
// COMPILE
// gcc -Wall -Wextra -Werror -O3 -s ./fputc.c -o ./fputc-test
// RUN
// ./fputc-test
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
void print_error_exit();
int main() {
FILE * fp;
// ensure file exists
if((fp = fopen("file", "w")) == NULL) print_error_exit();
// close stream
if(fclose(fp) == EOF) print_error_exit();
// open file in read-only mode
if((fp = fopen("file", "r")) == NULL) print_error_exit();
// close stream
if(fclose(fp) == EOF) print_error_exit();
printf("EOF is: %d\n", EOF);
// use fputc on a read-only closed stream (should return error, right?)
printf("fputc returned: %d\n", fputc(97, fp)); // 97 is ascii for 'a'
// expected:
// prints EOF (probably -1)
// actual:
// prints 97 on linux with both gcc and clang (multiple versions tested)
// prints -1 on windows with mingw-gcc
return EXIT_SUCCESS;
}
void print_error_exit() {
fprintf(stderr, "%s\n", strerror(errno));
exit(EXIT_FAILURE);
}
I have tested the code on Ubuntu 20, Debian 9, Windows 10, using gcc 8.1.0, gcc 8.3.0, gcc 9.3.0, and clang 7.0.1. On windows, I've used mingw.
The only trend I found is that fputc returns what I would expect it to on windows, and does not return what I expect it to on linux.
Which one of the following is correct?
- There is a bug in my code (if there is, explain why and post fixed code please)
- I did not understand the spec correctly (if so, please explain it better)
- There is a bug in both gcc and clang when compiled for linux (where to report this?)
- There is a bug with linux (some distros or all) (where to report this?)
Please help me understand this. Why does fputc not return an error code (EOF) when I try to use it on a closed stream, let alone, a stream that was opened only for reading?
Solution
Your code exhibits undefined behavior.
From J.2 Undefined behavior:
The behavior is undefined in the following circumstances:
The value of a pointer to a FILE object is used after the associated file is closed (7.21.3).
After you close the file, it's invalid to use the FILE
object, and the pointer itself has indeterminate value.
Answered By - KamilCuk