Compiler Bug

A semi-mythical beastie.

Semi-mythical?? If only!

Real examples welcome, but only genuine compiler bugs, please. And those are fairly rare.

Of course, since most program have bugs, it will also happen that compilers have bugs. This is even more true if you consider optimizing compilers since optimizing code is a very complicated task. The advantage is that compilers are used very often, and thus most bugs are found quickly.


Counter: A Compiler is just a program that gets used a lot. Many programs have bugs.

CounterCounter?: :) While many programs have bugs, since a compiler tends to be used a lot more (and under very weird circumstances), most of its bugs get found early and fixed. So while bugs may have been common in v1.0 of the compiler, by the time it gets to v5.0 they're rare beasts indeed. But note that rare != extinct.

CounterCounterCounter?: Optimizing compilers are very complicated beasts. Despite the fact that they get used a lot, I doubt anyone has ever released a decent optimizing compiler which was known to not have ANY bugs. While it's more common for programmers to mistakenly assume things that are not guaranteed by the language and have those assumptions violated by the compiler only with optimizations turned on, I'm sure there are lots of programmers out there who have been bitten by the occasional optimizer bug. I've heard it said that for mission-critical applications you're better off compiling with the optimizer turned off...

http://gcc.gnu.org/gcc-3.2/changes.html

This list of bugs fixed between GCC 3.2 and GCC 3.2.3 is interesting. I wonder how many developers encountered each of those bugs between 3.2 and 3.2.3? I wonder how long each bug was in the compiler before 3.2 without being detected? Perhaps some bugs existed for a long time without ever manifesting themselves during operation of the compiler. On the other hand, perhaps some of those bugs *did* manifest themselves in the form of subtle failures in large compiled programs, but without the compiler bugs themselves being detected and identified. FWIW, I consider GCC to be one of the more reliable/trustworthy compilers out there. Compiler bugs are semi-mythical because they are hard to find, NOT because they don't exist. =)


I can remember the details of three examples (I've seen a few more; they seem to be more common in compilers for embedded systems).

  case '2':
    which = choose_recipe();
        /* temporary needed to workaround compiler bug */
    edit_recipe(which);
    break;

edit_recipe(choose_recipe()) triggered the bug - IIRC it passed an incorrect value to edit_recipe. This was in compiler for embedded 68K systems made by Crossware.

Another bug in the same compiler, happened when the last line of a source file had no trailing newline, and the compiler was set to generate assembly: it would mangle the assembler output.

To be fair to Crossware, they fixed these two bugs very promptly.

Also in Analog Devices Visual DSP++, there was a HeisenBug in the linker that depended on the order of object modules in the linker definition file. Never did work out exactly what the bug was, but it went away with the next version.

I've also seen 3 or 4 bugs in Sun's javac compiler.

Long ago I found and reported a very severe bug in Sun's C compiler optimizer (it optimized a local variable initialization out of existence). It took them 2 years to fix it.


Well, machine X's cc implementation Y at version Z had the bug that in expressions like 0 * do_something(x), where either operand of multiplication could be statically proven to be zero, the expression was statically reduced to 0. It seems it didn't occur to them that the other operand might have side effects.


Question: Do all bugs in the compiler count as CompilerBugs?, or must the bug appear in the program output from the compiler as a result of a correct input?

Finding bugs in a compiler is easy, almost trivial - I used to be able to routinely feed valid C++ code into gcc and cause segfaults or fatal error messages. I can't do this so easily any more, since all the bugs I know of are fixed, and I haven't found the new ones yet, mostly because they require sexier C++ than I know.


In fact they're so rare that my only shining example just disappeared! I used to have a case where the compiler would mysteriously corrupt the name of a single class if and only if it was compiled using PrecompiledHeader?s. But when trying to get the exact details to post here, I discovered that even after removing the workaround I'd made to get around the problem, it didn't seem to recur (despite 100% reliably causing the problem mid last year). And I'm 100% certain that the file itself hasn't been modified since then. Go figure. -- GavinLambert


While is is certainly true that people often blame the compiler as a first resort, it's also true that bugs do exist in many compilers. To find them, try doing things that most people don't (like building Linux kernels). Here's one of my early finds:

http://groups.google.com/groups?q=tolerant!dws+pcc&hl=en&selm=140%40tolerant.UUCP&rnum=1

Not everybody is building Linux kernels? Oops, time to take off the blinders.

Bugs in the GnuCompilerCollection (GCC) may be found via http://www.gnu.org/software/gcc/bugs.html.


The milder form of putting blame on a CompilerBug is accusing the standard libraries. ThePragmaticProgrammer answers "SelectIsNotBroken?" to this.

Counter: The latest release of glibc fixes a number of threading bugs. My team ran into one of them.


In school, I was taking a course taught in PL/1 [PliLanguage], and found a bug in that compiler - it would not correctly reference arrays of structures or structures of arrays. I spent half a semester's worth of computer money to determine this, and the professor was quite upset that I found such a thing. But did you complete the assignments on time, and what was your final grade for the class?

I passed with an A or B, but this prof was the kind who disliked contact with students - not available except during the minimum number of office hours, which were 6am-7am, very abrupt with answers to questions, etc.


Many years back, a CS prof got to the place in his notes where he would tell the class to avoid a particular construct in Pascal [PascalLanguage], because the (Hamburg) Pascal compiler had a bug. He was not amused to hear that two of us in the class had fixed the bug the week before. He didn't like the idea of having students (even those working for the college computer center) getting their hands on software he depended on. -- DaveSmith


Earlier this year, I was working on an assignment in PascalFC - concurrent Pascal. Turns out the compiler had a hard limit on the number of identifiers allowed in a program; the only solution, short of recompiling the binary (the lecturer probably would prefer not to have to recompile) was to rewrite the entire solution using a different ConcurrentProgramming paradigm. (Not sure if this is a bug or not :P) -- JevonWright?


I get "Internal Compiler Error" messages from the Visual C++ compiler (6.0 and earlier versions) a couple of times per month. Interestingly, re-running the compile often works - the problems are not reproducible with the same source files. (Same happens to me in Delphi (at least 4 and 5). Having the whole program recompiled (instead of just the bits that changed) usually fixes the problem.)

I got some Visual C++ errors regarding TemplateSpecializations once... they may or may not have been fixed by now.

I get this kind of stuff a lot from the incremental compile/incremental link features of Visual C++. I have one particular project which, when set to do a batch build (it consists of 8 separate binaries), invariably fails at least once with a segfault in either the compiler or the linker. A second batch build invariably succeeds. I think this has to do with the build chain losing track of its intermediates and forgetting what data belongs to what build. Thankfully, this seems to be mostly gone in the 200x versions of the build chain. Trying to debug a module based on a corrupted Intellisense database and a corrupted symbol database is a supremely surreal experience, especially late at night.


It's interesting that nobody has mentioned any bugs in the JavaCompiler. Besides well known ones like volatile not being implemented, at least for the first few versions? -- AdamBerger


Under VxWorks (Tornado 2.0), the compiler is gcc (cygnus-2.7.2-960126 egcs-971225 tornado 2.0). Several compiler bugs have been observed, especially in C++. Here are the two most interesting:

1. The C++ code was more complicated than outlined, but the important statements have been pulled out to demonstrate the bug. int k = 0; Object.array[k++]; assert (k == 1); would assert every time. 'k' had the value of '2'. The workaround was to increment 'k' outside of array index.

2. A routine, this one in C, compiled out most of the routine as viewed through assembly. The compiler couldn't optimize the code out (and optimization wasn't even enabled). It goes as such: void func (void* a) { if (!a) return; // followed by more code }. The 'more code' was compiled out. To get around the problem, the 'return' statement had to be put within curly braces.


Years ago I encountered a bug in a C compiler on a Unisys Unix box. If optimization was enabled, the program did not work as written. The simplest work around we could find was to insert one extra statement.

    k = k;
Henceforth, strange problems were met with the comment, "k=k".


I run into about one gcc bug a month. Mostly they're internal compiler errors, nice clean crashes, so you can report them and find a workaround. The more evil type is code generation bugs, things that almost work, or even almost-kinda-usually work... ran into one today, ate half my day before I convinced myself it was real. Known problem, it turns out. Grr! -- AdamBerger


Some funny bugs in Delphi 6:


Just today, I was compiling a Java class with the stock Sun's 1.4.2_06 JavaCompiler and it failed to compile it - the method in question was creating an instance of AnonymousInnerClass based on an interface. The compiler insisted that the creation of the instance can throw an exception, whereas I knew it can't (compling through EclipseIde also went without problems). A method inside the class could throw the exception, though. Anyway, I had few similar methods and looked around what's different. The only difference was that other methods had a local variable declaration. When I added a simple and completely redundant "int x;" in front of the inner class instantiation, the compiler suddenly could get over it. -- AttilaSzegedi


Compiler bugs are often found lurking in parts of the compiler that are infrequently exercised. A good way to find some of these is to bombard the compiler with many randomly generated programs. This technique will usually find bugs in a compiler (crashes, aborts, or incorrect code generation), unless the compiler has already been tested with just such a tool. See RandomTesting.


I found one once in Borland C++ Professional 3.0, under Windows 3.1. I started having odd crashes, which I couldn't figure out: every time I called a certain method, it crashed. Eventually, out of desperation, I tried moving my nested classes out into global scope (on the theory that there might be a bug in nested class support); amazingly enough, it worked. Move them back in, crash. So, I tried moving out just the one whose method was crashing; sure enough, that worked. Aargh. Eventually I wound up telling the compiler to show me the assembly. OK, nothing seems to be wrong with that method...what about the place where it's called...gibber, gibber. It turned out that the caller wasn't passing any parameters! What's more, the method's mangled name seemed to have been truncated to...63 characters...click! Yup, a shorter name fixed it. Obviously, despite the standard's declaration that there could be no length limits, and the documentation's claim that the limit was 255 characters, the linker really had a limit of 63, so the compiler had a workaround to truncate names to 63, and the workaround had a bug that kept parameters from being passed in.

-- JohnStracke?


Once while programming FORTRAN on a Data General O/S hosted on a third party mil-spec computer, my coworkers and I discovered a compiler bug. The compiler was generating the wrong code when expressions involving built-in trig functions were used. We were able to develop a test case where the FORTRAN code:

       x=1
       y=1
would get compiled into assembly language that boiled down to:

       x=1
       x=1
Unfortunately, the computer vendor had been sued by, and had countersued DG. So the chances the vendor would get DG to fix the bug were nil. We ended having to write a bunch of trig algorithms to verify the results of O/S calls.

-- Barry Fox


Version 1 of the C# compiler had an interesting bug in it. If you had:
  using( Type x = CreateXSomehow() )
      switch( y )
      { ... }
the compiler would crash (though this is valid C# syntax). Replacing it with
  using( Type x = CreateXSomehow() )
  {
      switch( y )
      { ... }
  }
(added curly braces around the switch statement) would make it work as expected.
If you want to be scared, read this:

http://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf

I'll never trust the compiler again.
I just hit a fun one today on HPUX IPF with STLPORT. The following fails to compile. Does a bug in a standard header count as a compiler bug? (Not even sure it's in the compiler's headers. Might be STLPORT.) Workaround is to include iostream before any using namespace std;.

namespace std {}

using namespace std;

#include <iostream>
I've seen a couple bugs that were clearly in the "well-tested" support software.

Back in the bad old mainframe days, I was writing code in FORTRAN on a MichiganTerminalSystem? over VM system. There were two FORTRAN compiler in use at that installatio, the IBM FORTRAN G and H compilers. I was warned to always use the G compiler initially and for testing, even though the H compiler produced much faster code, and was shown an example of a loop that was optimized into incorrectness by the H compiler, though the G compiler handled it just fine. It may have been the issue at http://osdir.com/ml/emulators.hercules390.general/2003-04/msg00219.html

The other problem I had that was probably a compiler problem (though it could have been the linker) was a floating point exception in the middle of a module that was entirely integer calculations. This was using Microsoft C, probably 4.0 or 5.0 on a MS-DOS 3.1 system. The fix happened when I reorganized the code in the process of debugging, where I swapped a couple lines around. I was under deadline pressure and didn't have time to worry about it any further than that.
Before yesterday, I used to trust C++ compilers. I understood that some had bugs in rare corner cases, or were not standards compliant and would simply not compile valid constructs, but that trust was broken.

http://groups.google.com/group/comp.lang.c++/msg/a657a7799d8b953d

https://connect.microsoft.com/VisualStudio/feedback/details/336316/missing-destructor-calls-when-optimization-is-enabled

Short version: In C++, under basically all visual studios versions as far as I can tell, if you have a function with a return type of a class type by value, you return a stack object, and there is exactly one return statement, then the destructor of that stack object will not be called from execution running past the end of its containing block / scope. Ex:

class foo { foo(); ~foo(); };

foo bar()

{ for (int i=0; ; ++i)
  { foo x;
    if (i == 2)
      return x;
  } //XXX
}

At XXX, when execution reaches the end of this block, the for-body, the destructor of x should be automatically called. With this bug in the optimizer related to "named return value optimization", it skips the destructor call of x at XXX. This is the most heinous compiler bug I have ever seen. UPDATE: Apparently because of the thread in the newsgroup and some insider reading it, they've finally decided to fix it for VS 2010 in the next service pack. +1 karma points for Microsoft. ...and, for taking so long to fix the problem, -1 karma points for Microsoft.


CategoryBug

EditText of this page (last edited March 18, 2010) or FindPage with title or text search