Home

This page lists bugs in C compilers with which I have firsthand experience. This page is mainly for compilers used to develop software for embedded systems.

MinGW32 2.95.2 (probably old CygWin, too)

BSS size is not stored in the correct field of the section header

Because of this bug, linking MinGW 2.95.2 object files with object files created by other tool chains (e.g. NASM) may produce defective executable files.

Code and command-line: mingbug.zip
Workaround: the new version of MinGW available from SourceForge does work properly with NASM (though the BSS size still appears to be in the wrong field).

Linker crashes trying to make a binary file

You may be able to use objcopy to convert a regular PE executable to binary. Or, link like this:
        ld --oformat pei-i386 --file-alignment 0x1000 --section-alignment 0x1000 ...
then skip over (ignore) the 4096-byte PE header.

DJGPP COFF != PE COFF

This is more of a "gotcha" than a bug. DJGPP COFF relocations work differently than Win32 PE relocations. If you're mixing and matching software tools, know which COFF you're using.

MinGW 3.2

'strip' changes file alignment

'strip' 2.13 changes the file alignment of Win32 PE COFF executables.

'ld -Ttext=NNN ...' sets incorrect virtual address

'ld -Ttext=NNN ...' (NNN != 0) locates section .text at virtual address 0. To fix this, use 'ld -Ttext=NNN --image-base 0 ...'

Turbo C 2.0 (for x86 CPU)

intr() function is buggy

intr() does not load the BP register properly.
Workaround: write your own intr().

Compiler 'misplaces' local variables declared 'static const'

Workaround: don't use both modifiers for local variables.

printf() does not print floats properly

This bug, in Turbo C 2.0 (__TURBOC__==0x18D), was reported to me by John Payson.
I did just find a nasty bug in printf, though--in particular, the "%f" formatting [though %g may have similar issues].
	printf("%1.0f",999.6);
Should output "1000". Instead, it outputs "100". In general, the printf routine messes up if rounding a number to the required precision would change the required field size. For example:
	printf("[%5.1f]",999.93);
	printf("[%5.1f]",999.98);
	printf("[%5.1f]",1000.03);
will output "[999.9][1000][1000.0]"
Workaround: a patch is available from Borland. Alternately, you can use Turbo C++ 1.0 instead, which, like Turbo C 2.0, is a free download.

Turbo C++ 3.0 (for x86 CPU)

Huge pointer math does not work

Code and command-line: tcc -v -O tcbug3.c
Assembly-language output: tcbug3.lst
Workaround: NONE. The bug is not in the PADA@ pointer addition routine in the C library, but rather, in the compiler itself. A C++ huge pointer class, with properly overloaded math and indirection operators, might fix the problem. If you need to work with objects larger than 64K, you should use a different compiler (preferably a 32-bit compiler such as GNU C).

Compiler thinks -32768 is long

Code and command-line: tcc -v -O -w tcbug2.c
Erroneous code is not generated by this bug; just a spurious warning.

Trouble with shifts.

Code and command-line: tcc -v -O tcbug1.c
Assembly-language output: tcbug1.lst
Workaround: give << and >> their own line of code (don't use them in complex expressions), or shut off optimization (don't use -O option).

biosdisk() may not return what you think

This function returns the 8-bit error code left in register AH by the call to INT 13h. It does NOT return a combined, 16-bit error code + number of sectors transferred, as described in the online help.

Borland C/C++ version 3.1 (for x86 CPU)

Optimization causes volatile to fail

The offending optimization is 'Move Invariant Code out of Loops' (-Om on the command line), and the error appears in conjunction with other optimizations (those enabled by -O2).

Code and command-line: bcc -v -O2 bcbug1.c
Assembly-language output: bcbug1.lst
Workaround: compile without this optimization:
bcc -v -O -Ob -Oe -Og -Oi -Ol -Op -Ot -Ov -k- -Z bcbug1.c

Trouble calculating size of pointers to functions

Code and command-line: bcc -v -O2 bcbug2.c
Workaround: use casts and specify the pointer size manually:
Fn=(fnptr)((int)Fn + 2)); /* same as Fn++ */

32-bit registers not saved in interrupt routines

Code and command-line: bcc -v -O2 -3 bcbug3.c
Assembly-language output: bcbug3.lst
Workaround: don't use 32-bit code (-3 command-line option) with interrupt code.

K. Heidenstrom reports the same bug in Borland Pascal 7. See section 6.37 of pctim003.txt

Optimization may cause strchr() to fail

Code and command-line: bcc -Oi -Z bcbug4.c
Workaround: do not use -Z command-line optimization ("Suppress redundant loads"). Note that the -O2 and -O1 options imply -Z. Compiling with -O2 optimizations except for -Z should work:
bcc -O -Ob -Oe -Og -Oi -Ol -Om -Op -Ot -Ov -k- bcbug4.c

Thanks to Alexander Sorockin for sending me this bug.

More bugs in Borland C 3.1

Franklin C version 3.06 (for 8051 CPU)

This was an older version of what is now Keil C, and Keil C is greatly improved. I don't know if the customer service of Keil's distributors has also improved...

Bitwise OR to a global variable fails

Code and command-line:
c51 frcbug1.c cd sb ot(5) db oe sm
l51 frcbug1.obj,c:\frc\lib\c51fps.lib,c:\frc\lib\c51s.lib to frcbug1.abs co(0) xd(0) nool

Assembly-language output: frcbug1.lst
Workaround: Unknown.

Function calls deleted erroneously at high optimization levels

Code and command-line:
c51 frcbug2.c cd sb ot(5) db oe sm
l51 frcbug2.obj,c:\frc\lib\c51fps.lib,c:\frc\lib\c51s.lib to frcbug2.abs co(0) xd(0) nool

Assembly-language output: frcbug2.lst
Workaround: Avoid optimization greater than level 3:
c51 frcbug2.c cd sb ot(3) db oe sm

String literals are not character arrays

Code and command-line:
c51 frcbug3.c cd sb ot(5) db oe sm
l51 frcbug3.obj,c:\frc\lib\c51fps.lib,c:\frc\lib\c51s.lib to frcbug3.abs co(0) xd(0) nool

Assembly-language output: frcbug3.lst
Workaround: Use pointer variable instead of literal:
void main(void)
{       char *Foo;
        ...
        Foo=STRINGLIT;
	printf("Constant string as characters: <%c> <%c> <%c> <%c> <%c>\n\r",
                Foo[0], Foo[1], Foo[2], Foo[3],
                        Foo[4]);