It appears that the following inline accessor function to stdin doesn't do it's job if -O2 optimization is turned on, thus letting a null pointer pass and causing a segfault. This doesn't happen if the function is not declared inline. Version: gcc (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu3) Command line: gcc -O2 -o fault fault.c GNU libc 2.7 is known for its non-constant stdin and is probably required to actually get a segfault. Code in readable format: #include <stdio.h> struct iostream { FILE *f; }; static struct iostream our_stdin = { 0 }; inline void access_iostream(struct iostream* ios) { if (ios->f == 0) if (ios == &our_stdin) ios->f = stdin; } void read_char(struct iostream* ios) { access_iostream(ios); fgetc(ios->f); } int main() { read_char(&our_stdin); return 0; }
Created attachment 16707 [details] preprocessed source
Works just fine here, with both 4.3 and 4.4, -O2 and -O0.
Works for me on 4.1.3 20080308 (prerelease) (Ubuntu 4.1.2-21ubuntu1) and (Ubuntu 20081013-0ubuntu2) 4.3.3 20081014 (prerelease), too. But not in 4.2.4 (Ubuntu 4.2.4-1ubuntu3).
I found an even shorter way to make it segfault, with no inline functions at all. It's an -O2 problem, then. #include <stdio.h> struct iostream { FILE *f; }; static struct iostream our_stdin = { 0 }; void read_char(struct iostream* ios) { if (ios->f == 0) if (ios == &our_stdin) ios->f = stdin; fgetc(ios->f); } int main() { read_char(&our_stdin); return 0; }
GDB output showing that libc (debug) received a null pointer: Program received signal SIGSEGV, Segmentation fault. _IO_getc (fp=0x0) at getc.c:40 40 _IO_acquire_lock (fp); (gdb) print fp $1 = (FILE *) 0x0 (gdb) up #1 0x000000000040051e in main () at fault.c:20 20 read_char(&our_stdin); (gdb) print our_stdin.f $2 = (FILE *) 0x7f75cc0c96a0 (gdb) print stdin $3 = (struct _IO_FILE *) 0x7f75cc0c96a0
This is most likely one of the aliasing bugs. Does -fno-strict-aliasing fix the issue?
(In reply to comment #6) > This is most likely one of the aliasing bugs. Does -fno-strict-aliasing fix > the issue? Nope. I did a little research and it seems that -fno-tree-vrp fixes it.
Closing 4.2 branch, fixed in 4.3.