Exception and controlfp issue in 64bit mode.

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
Hi,

I have a little issue with 64bit and exception and FPU state.
The following code works fine in 32bit but fails in 64bit due probably to a bug in the exception frame handling code.

            const unsigned int original=_controlfp(0, 0);
            unsigned int restored = 0;
            try
            {
                const unsigned int flipped=(_MCW_RC^original);
#ifndef _WIN64
                unsigned int control_mask = static_cast<unsigned int>(-1);
#else
                unsigned int control_mask = _MCW_EM | _MCW_RC | _MCW_DN;
#endif
<div style="margin-left:40px       unsigned int changed_state = _controlfp(flipped, control_mask);

                throw std::exception("Testing");
            }
            catch (std::exception&)
            {
                unsigned int control_mask = _MCW_EM | _MCW_RC | _MCW_DN;
                restored = _controlfp(original, control_mask); //CALLSTACK DISPLAYED BELOW
            }

            unsigned int new_state = _controlfp(0, 0);
            ASSERT(original==new_state));


In the catch the code is supposed to restore the state and you can check that the restored value is indeed equal to the original one.

However the new_state after the catch is equal to changed_state and not the original as expected.

As far as I can see the state is saved after the exception is thrown and restored after the last line of code in the catch by some code in NTDLL (restoration of xmm register done there too).

The call stack in the catch code shows:
     test.exe!test()::catch$0()  Line 69    C++
     msvcr80d.dll!_CallSettingFrame()  Line 36    Asm
     msvcr80d.dll!__CxxCallCatchBlock(_EXCEPTION_RECORD * pExcept=0x000000000012cfd0)  Line 1342 + 0x15 bytes    C++
>    ntdll.dll!0000000077ef3712()    

Then once done the code continues and end up doing...

0000000077EF3799  movdqa      xmm14,xmmword ptr [rcx+280h]
0000000077EF37A2  movdqa      xmm15,xmmword ptr [rcx+290h]
0000000077EF37AB  ldmxcsr     dword ptr [rcx+34h]

That last line restores the status that was present at the time of the exception I think invalidating the whole process.


Any advice on how to fix that if its possible at all.
(Code above compiled and tested in 64bit with VS2005 SP1 on an AMD64 machine)

Thanks.

Laurent




View the full article
 
Back
Top