automated exception handling for common data types

Started by
15 comments, last by irreversible 17 years, 9 months ago
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... :/
Advertisement
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)?

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

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..
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.
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.
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.
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.

This topic is closed to new replies.

Advertisement