When C++ code casts a double to unsigned long, VC12 generates a call to library function _dtoui3. If the double is infinite or NaN, the _dtoui3 function performs an unbalanced push onto the processor's floating point stack. If this happens eight times, the floating point stack becomes completely full, and subsequent floating point stack operations may fail. This is a regression from previous versions of Visual Studio.
The sample program performs some operations in a loop eight times. It is expected that all of these operations return the same result every time they are called. However, by the eighth iteration, the floating point stack is depleted, and DoSomeMath has unexpected behavior. This is a contrived sample, but it is based on code from a real application.
Expected result:
CastToULong: 0 DoSomeMath: 42
CastToULong: 0 DoSomeMath: 42
CastToULong: 0 DoSomeMath: 42
CastToULong: 0 DoSomeMath: 42
CastToULong: 0 DoSomeMath: 42
CastToULong: 0 DoSomeMath: 42
CastToULong: 0 DoSomeMath: 42
CastToULong: 0 DoSomeMath: 42
Actual result:
CastToULong: 0 DoSomeMath: 42
CastToULong: 0 DoSomeMath: 42
CastToULong: 0 DoSomeMath: 42
CastToULong: 0 DoSomeMath: 42
CastToULong: 0 DoSomeMath: 42
CastToULong: 0 DoSomeMath: 42
CastToULong: 0 DoSomeMath: 42
CastToULong: 0 DoSomeMath: -2147483648
------------------------------------------------------------------------------
#include <stdio.h>
#include <math.h>
__declspec(noinline) void CastToULong(double d)
{
unsigned long ul = static_cast<unsigned long>(d);
printf("CastToULong: %u\t", ul);
}
__declspec(noinline) void DoSomeMath(int x)
{
double d = ceil(x * 0.0034);
int n = static_cast<int>(d);
printf("DoSomeMath: %d\n", n);
}
int main(int argc, char* argv[])
{
for (int i = 0; i < 8; i++) {
CastToULong(INFINITY);
DoSomeMath(12345);
}
return 0;
}

Bruce Dawsonon 5/16/2014 at 3:06 PMI have confirmed that this bug is fixed in VS 2013 Update 2.