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.
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.
'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 ...'
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.
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]);