Board index » cppbuilder » Exceptions, VCL, & FPU

Exceptions, VCL, & FPU


2005-05-10 04:08:08 AM
cppbuilder60
Can anyone explain the behavior of this code?
TDateTime date;
WORD y1,m1,d1;
WORD y2,m2,d2;
_control87(MCW_EM, EM_ZERODIVIDE); // any exception mask will do
date = EncodeDate(1999,1,1);
DecodeDate(date, y1,m1,d1);
try{
throw Exception("TEST");
}
catch(Exception&){
}
DecodeDate(date, y2,m2,d2);
if (y1 != y2 || m1 != m2 || d1 != d2){
::MessageBox(NULL, "Wrong date calculated.", "Date Error",
MB_OK);
}
If the call to _control87() or the throw is removed, there is no
problem.
Regards,
Bruce
 
 

Re:Exceptions, VCL, & FPU

Once I tried to use MS VC DLL in my BCB6, but I step
into problems like "division by zero error", which were not
present in the original MS VC++ code that called the same
DLL.
Then I was told that MS & Borland interprets the division
by zero on different ways. Borland stops the execution and
MS do not.
I had to add these two lines to make my BCB6 code to
behave the same as MSVC++:
// Secure CPU
_clear87();
_control87( PC_64|MCW_EM, MCW_PC|MCW_EM );
I'm not sure if that can help you in any way to realize why they
used _control() functions.
--
Best regards,
Vladimir Stefanovic
" Bruce Salzman" < XXXX@XXXXX.COM >wrote in message
Quote
Can anyone explain the behavior of this code?

TDateTime date;
WORD y1,m1,d1;
WORD y2,m2,d2;

_control87(MCW_EM, EM_ZERODIVIDE); // any exception mask will do
date = EncodeDate(1999,1,1);
DecodeDate(date, y1,m1,d1);
try{
throw Exception("TEST");
}
catch(Exception&){
}
DecodeDate(date, y2,m2,d2);
if (y1 != y2 || m1 != m2 || d1 != d2){
::MessageBox(NULL, "Wrong date calculated.", "Date Error", MB_OK);
}

If the call to _control87() or the throw is removed, there is no problem.

Regards,
Bruce

 

Re:Exceptions, VCL, & FPU

Quote
I had to add these two lines to make my BCB6 code to
behave the same as MSVC++:

// Secure CPU
_clear87();
_control87( PC_64|MCW_EM, MCW_PC|MCW_EM );

I'm not sure if that can help you in any way to realize why they
used _control() functions.

Thanks for the response, Vladimir.
I ran into this because I needed to mask the floating point exceptions
to use MS's opengl32.dll, and the conventional wisdom is to do a
_control87(MCW_EM, MCW_EM);
It seems to work for the floating point exceptions, but if a VCL
exception is raised afterwards, the floating point precision is
reduced (to 64 bits I think) and the RTL (DateTimeToTimeStamp() in
sysutils.pas) cannot calculate dates properly anymore(!). Something
odd happens to the FPU state when a VCL exception is handled.
 

{smallsort}

Re:Exceptions, VCL, & FPU

Bruce Salzman wrote:
Quote
I ran into this because I needed to mask the floating point exceptions
to use MS's opengl32.dll, and the conventional wisdom is to do a
_control87(MCW_EM, MCW_EM);

It seems to work for the floating point exceptions, but if a VCL
exception is raised afterwards, the floating point precision is
reduced (to 64 bits I think) and the RTL (DateTimeToTimeStamp() in
sysutils.pas) cannot calculate dates properly anymore(!). Something
odd happens to the FPU state when a VCL exception is handled.
Perhaps part of exception cleanup is to reset the FPU?
It might be trying to reset it to the way it remembers (before the
subroutine), and the FPU gets confused.
Have you tried setting the control at the very beginning (WinMain or
wherever the earliest you get control is at ) ?
Have you tried setting the control again inside the catch?
You might also read SafeLoadLibrary() in BCB5.hlp. Wonder if that has
anything to do with it.
Oh, wait....
"DLL initialization code
DLL startup code no longer sets the FPU control word. See Changes to
DLL initialization code."
Might also look at Set8087CW() in the same help.
And "Changes to DLL initialization code"
 

Re:Exceptions, VCL, & FPU

Quote
Might also look at Set8087CW() in the same help.
Hi, Bob
Interesting. Somehow I never found that function in the help. It
appears that the VCL exception handler does restore the control word,
but _control87() confuses it. If I call GetPrecisionMode() before
executing my sample code, it returns pmExtended. After the exception,
it returns pmSingle.
If I use Set8087CW(0x133F) instead, it stays pmExtended.
Thanks,
Bruce