Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Once in a while C++ code will not work when compiled with some level of optimization. It may be compiler doing optimization that breaks the code or it may be code containing undefined behavior which allows the compiler to do whatever it feels.

Suppose I have some piece of code that breaks when compiled with higher optimizations level only. How do i know if it's the code or the compiler and what do I do if it's the compiler?

share|improve this question
28  
Most likely its you. –  littleadv Sep 26 '11 at 7:54
3  
@littleadv, even the recent versions of gcc and msvc are full of bugs, so I would not be so sure. –  SK-logic Sep 26 '11 at 7:57
2  
You have all warnings enabled? –  user1249 Sep 26 '11 at 11:18
    
@Thorbjørn Ravn Andersen: Yes, I do have them enabled. –  sharptooth Sep 26 '11 at 11:20
3  
FWIW: 1) I try not to do anything tricky that might tempt the compiler to mess up, 2) the only place the optimization flags matter (for speed) is in code where the program counter spends a significant fraction of its time. Unless you're writing tight cpu loops, in many applications the PC spends essentially all of its time deep in libraries, or in I/O. In that kind of app, the /O switches don't help you at all. –  Mike Dunlavey Sep 26 '11 at 15:33
show 3 more comments

9 Answers

Getting a compile error on standard code or an internal compile error is more likely than optimizers being wrong. But i have heard of compilers optimizing loops incorrectly forgetting some side effects a method cause.

I have no suggestions on how to know if its you or the compiler. You may try another compiler.

One day i was wondering if it was my code or not and someone suggested valgrind to me. I spent the 5 or 10mins to run my program with it (i think valgrind --leak-check=yes myprog arg1 arg2 did it but i played with other options) and it immediately showed me ONE line that is ran under one specific case which was the problem. Then my app ran smoothly ever since with no weird crashes, errors or strange behavior. valgrind or another tool like it is a good way to know if its your code.

Side note: I once wondered why the performance of my app sucked. It turned out all of my performance problems was in one line as well. I wrote for(int i=0; i<strlen(sz); ++i) {. The sz was a few mb. For some reason the compiler ran strlen every time even after optimization. One line can be a big deal. From performances to crashes

share|improve this answer
add comment

In over 30 years of programming, the number of genuine compiler (code generation) bugs I've found is still only ~ 10. The number of my own (and other people's) bugs I've found and fixed in the same period is probably > 10,000. My "rule of thumb" then is that the probability of any given bug being due to the compiler is < 0.001.

share|improve this answer
    
You're lucky. My average is about 1 really bad bug a month, and minor borderline issues are a way much more often. And the higher optimisation level you're using, the higher are compiler error chances. If you're trying to use -O3 and LTO, you'd be very lucky not to find a couple of them in no time. And I only count here the bugs in release versions - as a compilers developer, I'm facing much much more of problems of that kind in my work, but that does not count. I just know how easy it is to screw up a compiler. –  SK-logic Sep 26 '11 at 10:00
    
25 years and I also have seen very many. The compilers are getting worse every year. –  dwelch Jan 14 '12 at 5:57
add comment

Examine the assembly code that resulted and see if it does what your source is calling for. Remember that the odds are very high that it's really your code at fault in some non-obvious fashion.

share|improve this answer
    
This is really the only answer to this question. The compilers job, in this case, is to get you from C++ to assembly language. You think it is the compiler...check the compilers work. It is that simple. –  dwelch Jan 14 '12 at 5:59
add comment

Isolate the problematic spot and compare the observed behavior to what should happen according to the language spec. Definitely not easy, but that's what you have to do to know (and not just assume).

I probably wouldn't be that meticulous. Rather, I would ask the compiler maker's support forum / mailing list. If it's really a bug in the compiler, then they might fix it. Probably it would be my code anyway. For example, language specs regarding memory visibility in threading can be quite counterintuitive, and they could become apparent only when using some specific optimization flags, on some specific hardware (!). Some behaviour could be undefined by the spec, so it could work with some compiler / some flags, and not work with some other, etc.

share|improve this answer
add comment
  1. Re-read your code thorougly. Make sure you aren't doing things with side-effects in ASSERTs, or other debug (or more general, configuration) specific statements. Also remember that in a debug build memory gets initialized differently - telltale pointer values you can check here: Debugging - Memory Allocation Representations. When running from within Visual Studio you are nearly always using the Debug Heap (even in release mode) unless you explicitly specify with an environment variable that this is not what you want.
  2. Check your build. It's common to get problems with complex builds in other places than the actual compiler - dependencies often being the culprit. I know that "have you tried completely rebuilding" is almost as infuriating an answer as "have you tried reinstalling windows", but it often does help. Try: a) Rebooting. b) Deleting all your intermediate and output files MANUALLY and rebuilding.
  3. Look through your code to check for any potential locations where you might be invoking undefined behavior. If you've been working in C++ for a while, you'll know there are some spots where you think "I'm not ENTIRELY sure I'm allowed to assume that..." - google it or ask here about that particular type of code to see whether it is undefined behavior or not.
  4. If that still doesn't seem to be the case, generate preprocessed output for the file that is causing the problems. An unexpected macro expansion can cause all kinds of fun (I am reminded of the time a colleague decided a macro by the name of H would be a good idea...). Examine the preprocessed output for unexpected changes between your project configurations.
  5. Last resort - now you really are in compiler bug land - look at the assembly output. This might take some digging and fighting just to get a handle on what the assembly is actually doing, but it's actually quite informative. You can use the skills you pick up here to evaluate micro-optimizations as well, so all is not lost.
share|improve this answer
add comment

I would say it is a safe bet in 99.9...% the vast majority of the cases that it is your code, not the compiler, which is broken. And even in the extraordinary case when it is the compiler, you are probably using some obscure language feature in an unusual way, for which the specific compiler is not prepared; in other words, you could most likely change your code to be more idiomatic and avoid the weak spot of the compiler. At any rate, if you can prove that you found a compiler bug (based on the language spec), report it the compiler developers, so that they may get it fixed some time.

I know this is not a straight answer to your question, others may be able to give you better help on this.

share|improve this answer
1  
99.9% sounds a bit too optimistic for me. Compilers (and especially, C++ compilers) are far from ideal. –  SK-logic Sep 26 '11 at 8:02
    
@SK-logic, fair enough, I have no statistics to back it. It is based on my own experience, and I admit I have rarely stretched the limits of the language and/or the compiler - others may do it more often. –  Péter Török Sep 26 '11 at 8:10
3  
-1 SK-log: 99.9% sounds too low to me. –  Ritch Melton Sep 26 '11 at 17:52
5  
@umlcat: most likely it was your code depending on unspecified behavior; on one compiler it matches your expectations, on another it doesn't. that doesn't means it's broken. –  Javier Sep 26 '11 at 18:54
1  
I agree with Crashworks, when talking about game consoles. It's not unusual at all to find esoteric compiler bugs in that specific situation. If you're targetting normal PCs, though, using a heavily-used compiler, then it's very unlikely that you'll bump into a compiler bug that nobody's seen before. –  Trevor Powell Jan 14 '12 at 8:00
show 5 more comments

If you want to know whether it is your code or the compiler, you have to perfectly know the specification of C++.

If doubt persists, you have to perfectly know x86 assembly.

If you are not in the mood of learning both to the perfection, then it is almost certainly an undefined behaviour that your compiler resolves differently depending on optimization level.

share|improve this answer
    
(+1) @mouviciel: It also depends if the feature its supported by the compiler, even, if its in the specification. I have a weird bug with gcc. I declare a "plain c structure" with a "function pointer", its allowed in the specification, but works in some situations, and doesn't in another. –  umlcat Sep 26 '11 at 18:07
add comment

I started writing a comment and then decided its too long and too much to the point.

I would argue that it is your code that is broken. In the unlikely event that you've discovered a bug in the compiler - you should report it to the compiler developers, but that's where the difference ends.

The solution is to identify the offending construct, and refactor it so that it would do the same logic differently. That would most likely solve the issue, whether the bug is on your side or in the compiler.

share|improve this answer
add comment

Just as usual, as with any other bugs: perform a controlled experiment. Narrow down the suspicious area, turn off the optimisations for everything else and start varying the optimisations applied to that chunk of code. Once you get a 100% reproducibility, start varying your code, introducing things that might break certain optimisations (e.g., introduce possible pointer aliasing, insert external calls with potential side effects, etc.). Looking at the assembly code in a debugger might help as well.

share|improve this answer
    
might help with what? If it is a compiler bug - so what? –  littleadv Sep 26 '11 at 8:04
1  
@littleadv, if it is a compiler bug, you can either try to fix it (or just report it properly, in full detail), or you can find out how to avoid it in future, if you're doomed to keep using this version of your compiler for a while. If it's something with your own code, one of the numerous C++-ish borderline issues, this kind of scrutiny also helps in fixing a bug and avoiding its kind in future. –  SK-logic Sep 26 '11 at 8:07
    
So as I said in my answer - other than reporting, there's no much difference in treatment, regardless of whose fault it is. –  littleadv Sep 26 '11 at 8:09
1  
@littleadv, without understanding the nature of a problem you're likely to face it again and again. And there is often a possibility to fix a compiler on your own. And, yes, it is not "unlikely" at all to find a bug in a C++ compiler, unfortunately. –  SK-logic Sep 26 '11 at 8:12
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.