• Advertisement
Sign in to follow this  

automated exception handling for common data types

This topic is 4242 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I can't seem to find a definitve answer as to whether overloading operators (specifically devision) for common data types (such as ints and floats) is possible or whether it is feasible (performance wise). I'd like to extend automated excpetion handling to third party code, which would include internal exception handling for common faults, such as division by zero without having to write nasty functions to do the job. [Edited by - irreversible on July 8, 2006 2:58:40 PM]

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
Quote:
Original post by irreversible
I can't seem to find a definitve answer as to whether overloading operators (specifically devision) for common data types (such as ints and floats) is possible or whether it is feasible (performance wise).


Sounds like a generally bad idea.

Quote:

I'd like to extend automated excpetion handling to third party code, which would include internal exception handling for common faults, such as division by zero without having to write nasty functions to do the job.


I'm not sure what you're trying to do - but adding your own operator overloadings won't change anything in any third party library you might already have.

Share this post


Link to post
Share on other sites
If you're on Windows, you can use Structured Exception Handling to trap div-0 and other hardware-level exceptions easily, without screwing around with operator overloading.

In general, I'd say that overloading operators for intrinsics is going to be a bad idea for performance in general. If you're having that much trouble with invalid data causing screwy mathematical situations (i.e. if div-0 is actually "common" as you say) then you've likely got some design issues.

Share this post


Link to post
Share on other sites
Mmkay - I tried it with the simplest possible test:


__try
{
int a = 0;
int b = 0;
a = a / b;
}
__except(GetExceptionCode() == STATUS_INTEGER_DIVIDE_BY_ZERO)
{
MessageBox(0, 0, "Error: Divide By Zero!", 0);
}




And it doesn't report anything. Note that I've set the EHa compiler flag.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
So what do we learn from this? We learn that not only is it a bad idea, it doesn't even work.

Share this post


Link to post
Share on other sites
Quote:
Original post by irreversible
Mmkay - I tried it with the simplest possible test:

*** Source Snippet Removed ***

And it doesn't report anything. Note that I've set the EHa compiler flag.



... That would be because your code is nonsensical. Read up a bit on SEH and its syntax. Your __except block is the culprit.

Share this post


Link to post
Share on other sites

__except(
rec = *(GetExceptionInformation())->ExceptionRecord,
con = *(GetExceptionInformation())->ContextRecord,
EXCEPTION_EXECUTE_HANDLER)


Does that make more sense?

It's trapping access violation exceptions, but not division by zero. In fact, there's no response from the system to division by zero (last I remember, the process was supposed to be stopped by the OS and an "undhandled exception" message displayed). I'm not sure why...

Share this post


Link to post
Share on other sites
That should work better, yes.

Any chance your div-0 is getting optimized away? Try reading a number from the console and then dividing that by 0.

Share this post


Link to post
Share on other sites
Quote:
Original post by ApochPiQ
That should work better, yes.

Any chance your div-0 is getting optimized away? Try reading a number from the console and then dividing that by 0.



Well, if the compiler can optimize away this, then I'm impressed :)

int d = rand() % 2;
if(d != 1) d = 1;
int a = d - 1;
int c = d / a; //should be 1 / 0



It won't react to stack overflow:

int overflow[100000000];



... and out of array bounds:

char beta[10];
beta[11] = 2;



... exceptions either.





I don't so much care for the stack overflow, but EXCEPTION_ARRAY_BOUNDS_EXCEEDED is just plain useful sometimes as it's pretty much the only thing you can't catch easily when debugging.

Share this post


Link to post
Share on other sites
The first two throw an exception quite reliably for me. Maybe you should post your entire test code so we can see if there's something else involved. (It might be that your CPU doesn't support hardware div-0 exceptions, or they're disabled for some reason, but that seems unlikely.)


The third will not throw an exception; detecting that is not so easy. (Think about it - if an exception was thrown every time you access an array out of bounds, why doesn't it reliably crash programs?) EXCEPTION_ARRAY_BOUNDS_EXCEEDED requires that the hardware supports bounds checking and some other housekeeping code has to be in place. In general, it's safe to say you'll never see this exception - and even if you do, never count on it occurring.

Share this post


Link to post
Share on other sites
Quote:
Original post by ApochPiQ
The first two throw an exception quite reliably for me. Maybe you should post your entire test code so we can see if there's something else involved. (It might be that your CPU doesn't support hardware div-0 exceptions, or they're disabled for some reason, but that seems unlikely.)


The third will not throw an exception; detecting that is not so easy. (Think about it - if an exception was thrown every time you access an array out of bounds, why doesn't it reliably crash programs?) EXCEPTION_ARRAY_BOUNDS_EXCEEDED requires that the hardware supports bounds checking and some other housekeeping code has to be in place. In general, it's safe to say you'll never see this exception - and even if you do, never count on it occurring.


I just did a little rebuild (takes ages if you have >50 files in the project; and changing excpetion handling options does require a full rebuild) and tested it in debug mode - the division by zero is caught as expected.

AS for EXCEPTION_ARRAY_BOUNDS_EXCEEDED - I'd be glad enough if it worked in debug mode because there's nothing that would ever come close, in terms of debugging time, to inadvertently writing over array bounds.

Why this is so important to me is 3rd part code that is executed in a different module - I need to be able to intelligently handle divisions by zero (which in my case, if the programmer is sloppy, can mean that the output of the plugin would most likely be garbage and not worth waiting for).


EXCEPTION_RECORD rec;
CONTEXT con;

__try
{
int d = rand() % 2;

if(d != 1) d = 1;

int a = d - 1;
int c = d / a;

float fa = 1.f;
float fc = fa / (fa - fa);

char str[1024];
sprintf(str, "%f %f %f", fa, fb, fc);

MessageBox(0, str, 0, 0);

int overflow[100000000];
}
__except(
rec = *(GetExceptionInformation())->ExceptionRecord,
con = *(GetExceptionInformation())->ContextRecord,
EXCEPTION_EXECUTE_HANDLER)
{
MessageBox(0, 0, "Undefined exception", 0);
}






The above code is like a knife and exceptions are like hot butter: integer division by zero, ignored; floating-point division by zero, ignored (produces the expected 1.#INF); stack overflow, ignored.

PS - I'm using purely structured exceptions and I can see absolutely no change in program behaviour no matter whether it's compiled with the /EHsc (C++ exception handling) or the /EHa (structured exception handling) flag.

PPS - I have floating-point exceptions enabled in compiler settings.

PPPS - I have an AthlonXP 1400+. I couldn't rightfully tell if it supports hardware div-by-zero exception notifications, but I'd sort of expect it to... :/

Share this post


Link to post
Share on other sites
If you pull the __try/__except out, does it crash as expected for each individual fault? What happens if you simplify the __except case to just __except(EXCEPTION_EXECUTE_HANDLER)?

Share this post


Link to post
Share on other sites
Quote:
Original post by ApochPiQ
If you pull the __try/__except out, does it crash as expected for each individual fault? What happens if you simplify the __except case to just __except(EXCEPTION_EXECUTE_HANDLER)?


As I mentioned, it also only crashes for access violations (!), and it makes no difference if the __except block is more complex than that or simply __except(EXCEPTION_EXECUTE_HANDLER).

I remember having the same problem in the past when I tried to add exception handling to my codeand I simply ended up giving up on it because I couldn't catch anything. I suppose it's possible there's a compiler flag I'm still missing, but I've looked 10-15 times now..

Share this post


Link to post
Share on other sites
Quote:
Original post by irreversible
Why this is so important to me is 3rd part code that is executed in a different module - I need to be able to intelligently handle divisions by zero (which in my case, if the programmer is sloppy, can mean that the output of the plugin would most likely be garbage and not worth waiting for).


If you're trying to create a robust sandbox for 3rd party plugins then C++ is probably not the right tool for the job.

Share this post


Link to post
Share on other sites
Quote:
Original post by OrangyTang
If you're trying to create a robust sandbox for 3rd party plugins then C++ is probably not the right tool for the job.


Unless, of course, there's the issue of "don't know how". And I don't mean for the sandbox to be so much robust, but simply provide the user with the option of not experiencing a rather silly crash or grossly waiting overtime because of badly designed third party code (the two primary exceptions - access violation and division by zero - are the most obvious and required things to handle) - in my case a division by zero can potentially render hours of succeeding computation pointless if the plugin doesn't handle it appropriately (especially with arbitrary, user-defined parameter values). Besides, it provides a very good testbed for the developer to make sure his/her plugin really is working under various unforeseen circustances without neccessarily having to implement exception handling in the plugin itself (even if it would be kind of nice).

All in all, capturing that particular exception could in this case sometimes prove to be just plain invaluable.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by irreversible
All in all, capturing that particular exception could in this case sometimes prove to be just plain invaluable.


Or maybe the third-party plugin, which has full write access to the entire address space of your process, has left your entire application in a completely compromised state.

So, what do you do when the plugin (which has complete access to the entire address space of your process, remember) barfs? Continue running!?? That's the worst possible course of action. Can you say data corruption? Or worse?

I'm sorry, this seems like putting a bandage over a broken bone. And then hitting the broken bone with a hammer just in case.

Share this post


Link to post
Share on other sites
I'm sorry, but IMO you're wrong.

If a plugin generates a division by zero, I can terminate (or stop) it and the host application will keep on running, giving the user a chance to change the input parameters for the plugin.

On the other hand, if it generates an access fault, I'll shut the plugin down, but not the host application unless the user wants to do so.

There's no way I can REALLY control what address space the plugin writes to - it's just a matter of how intelligently I can handle the outcome and how good feedback I can give the developer (eg if the plugin generates an access fault by accident, I can tell the developer roughly where the exception comes from without crashing and leaving them wondering if it might have been the host application that crashed instead). The same goes for div-by-zero, which is in many cases even more important for me.

So, in my opinion, it's not more of a security risk than not handling the exceptions at all or automatically terminating the host application when they arise; but much more a matter of good form.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement