Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / Managed C++ / March 2005

Tip: Looking for answers? Try searching our database.

Catching floating point errors

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Chris Stankevitz - 04 Mar 2005 23:08 GMT
Hi,

I have a very large Visual c++ .net 2003 7.1 native c application
(approximately 500,000 lines of code).  This application is a simulation
that frequently works with floating point numbers.

From time to time  I do something bad -- for example divide by zero or try
to grow a float beyond numeric_limits<float>::max()

I told MSVC .net 2003 7.1 to "Break into the debugger" for ALL exceptions in
the "Exceptions" dialog.  In particular, there is a red circle/x in all the
floating point related exceptions under "Win32 Exceptions" indicating the
debugger should break when it encounters such an exception.

Believe it or not, despite all my hard work making little red Xs, the
debugger does not always stop execution when I perform a funny float
operation.

My question: how do I have MSVC 7.1 .net 2003 break on funny floating point
errors?

PS: Each of my threads execute this code when they start up:
_control87(_EM_INVALID | _EM_DENORMAL |_EM_ZERODIVIDE | _EM_OVERFLOW |
_EM_UNDERFLOW | _EM_INEXACT, _MCW_EM);

Thanks,

Chris
William DePalo [MVP VC++] - 04 Mar 2005 23:33 GMT
> Believe it or not, despite all my hard work making little red Xs, the
> debugger does not always stop execution when I perform a funny float
> operation.
>
> My question: how do I have MSVC 7.1 .net 2003 break on funny floating
> point errors?

It may be that the runtime is masking the exceptions. Take a look at this

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt
__control87.2c_._controlfp.asp


and if it does not help, post again.

Regards,
Will
Chris Stankevitz - 05 Mar 2005 02:04 GMT
> It may be that the runtime is masking the exceptions. Take a look at this
>
> and if it does not help, post again.

Will,

That did not help.  I used control87 to tell the runtime to catch floating
point exceptions, but it still let one slip through.

Here's a screenshot of MSVC .net 7.1 2003 letting a sqrt of negative number
slip through:
http://www.stankevitz.com/visualstudio/stat.png

And here's a screenshot of me calling control87 just a few steps back on the
call stack:
http://www.stankevitz.com/visualstudio/control87.png

And here's a screenshot of my exception settings:
http://www.stankevitz.com/visualstudio/exceptions.png

FYI, this is the control87 line I used:
_control87(_EM_INVALID | _EM_DENORMAL |_EM_ZERODIVIDE | _EM_OVERFLOW |
_EM_UNDERFLOW | _EM_INEXACT, _MCW_EM);

Thanks for your assistance!

Chris
William DePalo [MVP VC++] - 06 Mar 2005 22:06 GMT
> FYI, this is the control87 line I used:
> _control87(_EM_INVALID | _EM_DENORMAL |_EM_ZERODIVIDE | _EM_OVERFLOW |
> _EM_UNDERFLOW | _EM_INEXACT, _MCW_EM);

I haven't had the "pleasure" of doing floating point calcualtions since the
'80s when mortgage backed securities were the rage so I had to read the help
for _control87() twice. <g>

Nevertheless, I just tried this in VS.Net 2003,

   float f;
   unsigned int u;

   u = _controlfp(0, 0);
   u = u & ~(_EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW |
_EM_UNDERFLOW | _EM_INEXACT);

   _controlfp(u, _MCW_EM);

   f = 1 / f;
   f = sqrt(-1.0f);

The last two lines raise exceptions in the debugger.

Regards,
Will
Chris Stankevitz - 08 Mar 2005 17:15 GMT
> Nevertheless, I just tried this in VS.Net 2003,

Will,

Thanks for your help.

Do these "control87" commands need to be issued on every thread in the app?
Do I need to constantly apply them to guarantee they "stick"?  Can other
processes disable them?  Can opening a common dialog (such as File | Open)
reset them?

Thanks,

Chris
William DePalo [MVP VC++] - 08 Mar 2005 18:39 GMT
> Do these "control87" commands need to be issued on every thread in the
> app?

As I said, I don't do any "scientific" calculation these days. But as the
exception mechanism of the platform _is thread based_, I think that the
answer is yes.

> Do I need to constantly apply them to guarantee they "stick"?

Good question. I don't know. I would guess that the runtime sets the
exception policy while processing the DLL_THREAD_ATTACH notification and not
thereafter. That's a guess. If you have the runtime source (disclaimer: I
can't say for certain how much is distributed with the VS.Net IDE) you might
want to take a look.

> Can other processes disable them?

I can't think of an easy way.

> Can opening a common dialog (such as File | Open) reset them?

Well, the thing to note about exception handlers under Win32 is that they
are stack-frame based (tabling for now the issue of "vectored" exception
handing). So, if you call on a common dialog and if it does something like
this

   __try
   {
    DoTheCommonDialogThing();
   }

   __except ( blah blah blah ... )
   {
    // swallow the exception and move on
   }

then you (the caller) will never see it.

Regards,
Will
Jan Bares - 09 Mar 2005 08:10 GMT
> processes disable them?  Can opening a common dialog (such as File | Open)
> reset them?

Hi,

just add to previous answers, some device drivers (e.g. HP printer drivers)
mask FPU exceptions and do not restore them back. So it can happen in your
program, that after call to some API (3rd party DLL or so), the exceptions
will be masked. On the contrary, some 3rd party DLL may not work due to
unmasked exceptions. (We unmasked FPU exceptions in AutoCAD 2k, and it won't
even start due to divion by zero)

Jan
Chris Stankevitz - 08 Mar 2005 17:30 GMT
> The last two lines raise exceptions in the debugger.

Ahh... I solved the problem.  I had the bits inverted in the first argument
to the _control87 function.

This raised a second problem (pun not intended).  When an invalid floating
point operation occurs and is caught by correct use of _control87, the call
stack gets hosed.  I cannot see where the exception happened in my code!

It appears the floating point error jumps the code into the kernel and blows
the call stack. :(

Anyone know how I can track down these floating point errors?

Thanks again for your help,

Chris
Chris Stankevitz - 08 Mar 2005 18:17 GMT
> It appears the floating point error jumps the code into the kernel and
> blows the call stack. :(

This example illustrates the point.  Create a console app and set exceptions
as shown here:
http://www.stankevitz.com/visualstudio/exceptions.png

Then compile/run this code:
//--------------------

#include <cfloat>
#include <cmath>

int main()
{
 _control87(0, _MCW_EM);

 sqrt(-1.0);

 return 0;
}

//--------------------

Thanks,

Chris
Chris Stankevitz - 08 Mar 2005 18:44 GMT
>> It appears the floating point error jumps the code into the kernel and
>> blows the call stack. :(

Turns out the call stack comes back if you "pass exception on the caller" a
few times.

Okay, my problem is solved, thanks for your help everyone!

Chris
Doug Harrison [MVP] - 08 Mar 2005 21:11 GMT
>Turns out the call stack comes back if you "pass exception on the caller" a
>few times.
>
>Okay, my problem is solved, thanks for your help everyone!

One more thing to consider is that FPU  exceptions are somewhat asynchronous
and may not be raised until a subsequent FPU  instruction is executed. You
can raise any pending FPU exceptions with:

__asm { fwait }

I just found an an article on MSDN which mentions this:

Microsoft Visual C++ Floating-Point Optimization
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/ht
ml/floapoint.asp


I haven't had a chance to read this article, but it looks very good.

Signature

Doug Harrison
Microsoft MVP - Visual C++

William DePalo [MVP VC++] - 08 Mar 2005 18:48 GMT
> This raised a second problem (pun not intended).

:-)

> When an invalid floating point operation occurs and is caught by correct
> use of _control87, the call stack gets hosed.  I cannot see where the
> exception happened in my code!

Does your exception handler call _clearfp()? I think that that is required
to clear the exception. I'm wondering whether your problem is that the
exception is signalled mre times than you think because it has not been
cleared.

As I said before in this thread, that's just a guess.

Regards,
Will
Vladimir Nesterovsky - 06 Mar 2005 09:13 GMT
I believe, the code does not throw. The reason is that the floating point
numbers have infinity and undefined values, which precludes undefined
results of operations.

> My question: how do I have MSVC 7.1 .net 2003 break on funny floating point
> errors?

You better check them manually.

Signature

Vladimir Nesterovsky
e-mail: vladimir@nesterovsky-bros.com
home: www.nesterovsky-bros.com

> I have a very large Visual c++ .net 2003 7.1 native c application
> (approximately 500,000 lines of code).  This application is a simulation
[quoted text clipped - 14 lines]
> My question: how do I have MSVC 7.1 .net 2003 break on funny floating point
> errors?
Chris Stankevitz - 08 Mar 2005 17:51 GMT
>I believe, the code does not throw.

Hi Vladimir,

Thanks for your help.  I suspect that *some* code causes FP exceptions to
throw or else they wouldn't have placed FP exceptions in this dialog:

http://www.stankevitz.com/visualstudio/exceptions.png

Thanks,

Chris

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.