M
Michael B. Brandl
Guest
Hi,
I encountered a problem executing c++ programs using floating point exceptions built on machines with several visual studio versions.
Consider the following program which sets the invalid-flag (wanting to raise floating point exceptions when NaN occurs),
then does floating point operations, and tests repeatedly if the flag is still set.
(None of the operations should result in a NaN):
// This tests if setting floating point exceptions via _control87 is stable
// with regards to std::acos.
#include <float.h>
#include <cmath>
#include <iostream>
void printException(unsigned int line)
{
unsigned int cw;
cw = _control87(0,0) & MCW_EM;
std::cout << "Line " << line << ": cw is " << cw << " which means "
<< (cw == 524319 ? "off" : // obtained values from testing
(cw == 524303 ? "on" :
"other"))
<< std::endl;
}
void activateException()
{
// See http://www.fortran-2000.com/ArnaudRecipes/CompilerTricks.html#x86_FP
unsigned int cw;
cw = _control87(0,0) & MCW_EM;
cw &= ~(_EM_INVALID);
_control87(cw, MCW_EM);
}
int main(int argc, char**)
{
double a, b;
printException(__LINE__);
activateException();
printException(__LINE__);
a = double(argc) - double(1.0); // Want: a = 0. Use this to prevent compiler from optimizing away.
std::cout << "a: " << a << std::endl;
printException(__LINE__);
b = std::acos(a); // Want: b = pi/2.
printException(__LINE__); // This line is the one showing wrong behavior in some cases.
std::cout << "b: " << b << std::endl; // Need this to prevent compiler from throwing b away.
return 0;
}
The expected output for the 4 calls to printException(...) is:
off
on
on
on
On machines with several visual studio versions installed (2008, 2010 and 2012), I got the following problem:
The 4th call to printException(...) gives "off" in some cases (meaning that the call to std::acos turned off floating point exceptions).
The cases are:
- On one machine (win7 64bit), for 64bit VS2008 and 64bit VS2010.
- On another machine (win7 64bit), only for 64bit VS2008.
the 32bit-versions and VS2012-versions are always working.
All visual studio versions are ultimate or pro, and on automatic update via windows update.
All versions have been installed chronologically (2008, 2010, 2012).
Here it says this seems to be supported by Microsoft:
http://msdn.microsoft.com/en-us/library/ms246609.aspx
All versions of the test program where compiled from command line, using
> cl testException.cpp
from the cmd-setups coming with the respective visual studio versions.
The environment varibles PATH and LIB set in these cmd:s looked correct (pointing to the correct directories for each VS-version).
Moving binaries of the test-program to other machines, the same behavior occurs as locally.
Running on a machine (win 7 64bit) with only VS2010, the x64 build worked well.
I have not tested with on a machine with only VS2008, though.
Using the depends-tool on the different resulting binaries shows that they use exactly the same versions of the kernel-dlls (kernel32.dll).
Any other ideas what could be wrong, or what could be tested?
Could this be a problem with the compiler or linker, or the .lib-files?
Continue reading...
I encountered a problem executing c++ programs using floating point exceptions built on machines with several visual studio versions.
Consider the following program which sets the invalid-flag (wanting to raise floating point exceptions when NaN occurs),
then does floating point operations, and tests repeatedly if the flag is still set.
(None of the operations should result in a NaN):
// This tests if setting floating point exceptions via _control87 is stable
// with regards to std::acos.
#include <float.h>
#include <cmath>
#include <iostream>
void printException(unsigned int line)
{
unsigned int cw;
cw = _control87(0,0) & MCW_EM;
std::cout << "Line " << line << ": cw is " << cw << " which means "
<< (cw == 524319 ? "off" : // obtained values from testing
(cw == 524303 ? "on" :
"other"))
<< std::endl;
}
void activateException()
{
// See http://www.fortran-2000.com/ArnaudRecipes/CompilerTricks.html#x86_FP
unsigned int cw;
cw = _control87(0,0) & MCW_EM;
cw &= ~(_EM_INVALID);
_control87(cw, MCW_EM);
}
int main(int argc, char**)
{
double a, b;
printException(__LINE__);
activateException();
printException(__LINE__);
a = double(argc) - double(1.0); // Want: a = 0. Use this to prevent compiler from optimizing away.
std::cout << "a: " << a << std::endl;
printException(__LINE__);
b = std::acos(a); // Want: b = pi/2.
printException(__LINE__); // This line is the one showing wrong behavior in some cases.
std::cout << "b: " << b << std::endl; // Need this to prevent compiler from throwing b away.
return 0;
}
The expected output for the 4 calls to printException(...) is:
off
on
on
on
On machines with several visual studio versions installed (2008, 2010 and 2012), I got the following problem:
The 4th call to printException(...) gives "off" in some cases (meaning that the call to std::acos turned off floating point exceptions).
The cases are:
- On one machine (win7 64bit), for 64bit VS2008 and 64bit VS2010.
- On another machine (win7 64bit), only for 64bit VS2008.
the 32bit-versions and VS2012-versions are always working.
All visual studio versions are ultimate or pro, and on automatic update via windows update.
All versions have been installed chronologically (2008, 2010, 2012).
Here it says this seems to be supported by Microsoft:
http://msdn.microsoft.com/en-us/library/ms246609.aspx
All versions of the test program where compiled from command line, using
> cl testException.cpp
from the cmd-setups coming with the respective visual studio versions.
The environment varibles PATH and LIB set in these cmd:s looked correct (pointing to the correct directories for each VS-version).
Moving binaries of the test-program to other machines, the same behavior occurs as locally.
Running on a machine (win 7 64bit) with only VS2010, the x64 build worked well.
I have not tested with on a machine with only VS2008, though.
Using the depends-tool on the different resulting binaries shows that they use exactly the same versions of the kernel-dlls (kernel32.dll).
Any other ideas what could be wrong, or what could be tested?
Could this be a problem with the compiler or linker, or the .lib-files?
Continue reading...