views:

300

answers:

4

Some math functions in a program I recently wrote are returning unacceptable values, such as NaN (possibly due to not checking some function's input params). The problem is that it's being quite difficult to track down which functions are passing the wrong values. This results in errors being propagated throughout the code and making the program crash minutes or hours later, if at all.

I wonder if there's a way to catch these faulty operations the moment a NaN value results from any operation (pretty much the same as in the 'DivisionByZero exception' thrown by some C/C++ compilers, if I remember).

Thanks in advance.

P.D: Please feel free to re-tag my question if needed.

+5  A: 

Without seeing your code this answer is going to be necessarily vague, but one way of doing it is to check the output from your function and if it's "NaN" raise and exception:

if (double.IsNaN(result))
{
    throw new ArithmeticException();
}

But with more details about the exception.

UPDATE

To trap where a specific exception is being thrown you could (temporarily) break when the exception is thrown in the debugger.

Select Debug > Exceptions then expand the tree to select Common Language Runtime Exceptions > System > System.ArithmeticException and check the "Thrown" option.

The problem with this is that it will break everywhere this is thrown, not just in your code. Putting explicit code at a low enough level gets around this.

ChrisF
What I want to do is to catch where the NaN value is produced without having to debug the whole application and writing a check like yours on every method that accepts doubles.
Trap
+1 That's exactly what I was looking for, thanks a lot for the update :)
Trap
I have the same problem, but the value that is bugging me isn't NaN but 'Infinity'. I checked the System.ArithmeticException as described above, but it doesn't fire, when my varibale is set to 'Infinity'. Is there an other Exception to check the Thrown option?
Aaginor
@Aaginor - you want the [`Double.IsInifinity`](http://msdn.microsoft.com/en-us/library/system.double.isinfinity.aspx) method
ChrisF
Like Trap, I want to catch when the Infinite value is produced, to get to know where the problematic part in my code is to be able to fix it - without the need to step through each single line to find out, where it is.
Aaginor
+3  A: 

Do you mean you are looking for some setting or option so that as soon as any int gets assigned the value NaN you want an exception to throw? I'm pretty sure no such thing exists. There is the checked option which will warn you about overflows, but thats not the same thing.

I think the only alternative to debugging by hand is to modify the code in the way ChrisF suggested. You could always put an #if DEBUG around the throw to stop if throwing in production code.

Steve Haigh
Yes, more specifically when any value type, not only int, gets assigned with NaN.
Trap
+1  A: 

I don't know if this works on the CLR, but you can use _controlfp_s from to trigger floating point exceptions:

unsigned int _oldState;
errno_t err = _controlfp_s(&oldState, 0, MCW_EM);
assert(!err);

To reset:

errno_t err = _controlfp_s(0, _oldState, MCW_EM);
assert(!err);
disown
You linked CRT (the C runtime library) help page, and at the bottom is indicates that this does not apply to the .NET runtime. OTOH, it does mention that you could use P/Invoke to call the C function.
Lucas
I'm not a .NET user, but it seems reasonable to assume that C# uses normal floating point instructions, and this should then be caught. If C# doesn't mess with these flags, _EM_INVALID should be triggered for NaNs, and if the mask is off you should get an FP exception.
disown
I also know that these exceptions are turned off by default in VC++ programs, so it could be worth a shot.
disown
A: 

You could always try a conditional break when in debug mode, following is the link to the full answer as I answered someone else with a similar question:

Conditional Debug

This will allow you to simply pause execution when the conditions are met, it may not be an exception but it should help you nonetheless.

Jamie Keeling