3

I noticed that my code broke at -O3, but not at -O2. I tried applying the flags one by one, and I found that

gcc -O1 -finline-functions code.c

breaks; and

gcc -O1 -fno-inline-functions code.c

works.

By "breaks," I mean that it compiles, but it runs incorrectly.

Where should I look for this bug? I can post code, but as it weighs in at 1.5k SLOC, I'd rather not post the whole thing.

Versions:

$ uname -a
Linux xxxx.xxxx 2.6.18-308.20.1.el5 #1 SMP x86_64 x86_64 x86_64 GNU/Linux
$ gcc -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --disable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=x86_64-redhat-linux
Thread model: posix
gcc version 4.1.2 20080704 (Red Hat 4.1.2-54)
Nick ODell
  • 15,465
  • 3
  • 32
  • 66
  • 1
    You are using a quite old GCC version, try updating it. This is likely a issue with undefined behavior or some "magic" function like `setjmp`/`longjmp`. Try to find which function causes the problem. – Guilherme Bernal Jun 25 '13 at 02:12
  • 1
    If you can narrow down the list of functions which might be causing the problem you can then test each one by individually disabling in-lining with the [noinline attribute](http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html) until you find the actual culprit. – sjs Jun 25 '13 at 02:49
  • Go through the process of creating an SSCCE ([Short, Self-Contained, Correct Example](http://sscce.org/)). When it is minimal, if RedHat still supports the compiler you're using, you can try reporting the problem to them. The GCC team won't be interested in the report against 4.1.x; they've long since given up supporting GCC 4.1.x (according to http://gcc.gnu.org/, 4.7.x is the oldest supported version). If you can reproduce the problem in 4.7.x or (better) 4.8.x, then you can report it to them. – Jonathan Leffler Jun 25 '13 at 06:44
  • @JonathanLeffler The program works in 4.4.7 with -finline-functions enabled. Odd. – Nick ODell Jun 25 '13 at 17:26
  • @sjs Thanks, that let me narrow it down. I figured it out, see answer. – Nick ODell Jun 25 '13 at 17:55

1 Answers1

5

I figured out the bug:

int foo() {
  return 5;
}
int bar() {
  foo(); // <-- no return statement!
}
int main() {
  printf("%d", bar());
}

See, even though there's no return statement in bar(), the value 5 is already in the return value register. main() picks up the value in the return register, thinking it's from bar, but really it's from foo. This is undefined behavior, but it only blows up if the compiler tries to inline bar(). The solution is to put a return in bar()

To gcc's credit, it does warn you if you turn on -Wall

code.c:63: warning: control reaches end of non-void function

I found this by manually applying __attribute__ ((noinline)) (thanks sjs!) to functions until my code worked correctly

Nick ODell
  • 15,465
  • 3
  • 32
  • 66