Hi. We had an “interesting” debugging experience here yesterday. After
finally tracking the problem down, it appears to be a bug in the Watcom
C++ compiler (version 10.6), specifically the optimizer.
In a nutshell, if a C++ const is defined in terms of a C++ library
function, the right set of optimizations will cause it to not be
properly evaluated for use during run time. Specifically for us, we had
a constant defined as such:
static const double TWO_PI = (4.0 * atan(1.0));
It started to get interesting when this appeared to be zero in some
spots, but the expected 6.28… in others. We finally caught the
difference - the modules that were compiled optimized (-Otrex -5 -fp5)
thought the constant was zero, while the unoptimized modules had the
correct value. We stepped through the startup code in wd and found
that, apparently, the optimizer was working too effectively - it was
removing instructions that it shouldn’t.
Sample code to duplicate this problem is below; it’s very easy to do.
I’m also looking into reporting this to the Open Watcom project. I’m
just posting this in hopes that it might help someone else.
Josh Hamacher
FAAC Incorporated
Sample code for generating this error follows. It consists of the
makefile, three c++ files, and one header file. The output is as
follows:
make all_unopt
./bug
Module 1 thinks TWO_PI is 6.28319
Module 2 thinks TWO_PI is 6.28319
make all_opt
./bug
Module 1 thinks TWO_PI is 0
Module 2 thinks TWO_PI is 0
make mixed
./bug
Module 1 thinks TWO_PI is 6.28319
Module 2 thinks TWO_PI is 0
\
Makefile
CC=cc
CFLAGS_OPT=-Otrex -5 -fp5 -w4 -M
CFLAGS_UNOPT=-g -w4 -M
all_unopt:
${CC} ${CFLAGS_UNOPT} -c -o mod1.o mod1.cpp
${CC} ${CFLAGS_UNOPT} -c -o mod2.o mod2.cpp
${CC} ${CFLAGS_UNOPT} -c -o bug.o bug.cpp
${CC} ${CFLAGS_UNOPT} -o bug bug.o mod1.o mod2.o
all_opt:
${CC} ${CFLAGS_OPT} -c -o mod1.o mod1.cpp
${CC} ${CFLAGS_OPT} -c -o mod2.o mod2.cpp
${CC} ${CFLAGS_OPT} -c -o bug.o bug.cpp
${CC} ${CFLAGS_OPT} -o bug bug.o mod1.o mod2.o
mixed:
${CC} ${CFLAGS_UNOPT} -c -o mod1.o mod1.cpp
${CC} ${CFLAGS_OPT} -c -o mod2.o mod2.cpp
${CC} ${CFLAGS_UNOPT} -c -o bug.o bug.cpp
${CC} ${CFLAGS_UNOPT} -o bug bug.o mod1.o mod2.o
end Makefile
// constant.h
#ifndef CONSTANT_H_INCLUDED
#define CONSTANT_H_INCLUDED
#include <math.h>
static const double PI = (4.0 * atan(1.0));
static const double TWO_PI = (2.0 * PI);
#endif
// end constant.h
// bug.cpp
#include <iostream.h>
extern double GetTwoPi1(void);
extern double GetTwoPi2(void);
int main(int argc, char *argv)
{
cout << "Module 1 thinks TWO_PI is " << GetTwoPi1() << endl;
cout << "Module 2 thinks TWO_PI is " << GetTwoPi2() << endl;
return 0;
}
// end bug.cpp
// mod1.cpp
#include “constant.h”
double GetTwoPi1(void);
double GetTwoPi1(void)
{
return(TWO_PI);
}
// end mod1.cpp
// mod2.cpp
#include “constant.h”
double GetTwoPi2(void);
double GetTwoPi2(void)
{
return(TWO_PI);
}
// end mod2.cpp
), but I am