Advertisement

Error handling: Opinions?

Started by September 27, 2000 02:29 PM
43 comments, last by Aienthiwan 24 years, 3 months ago
Ok well, my little idea for error handling sadly wasn''t as bright as I thought. As for why exactly I just don''t use error classes Countach said it himself, VisualC++ 6 doesn''t have full support of it. That pretty crappy to me mind you, a hard-core full featured compiler (and probably the best one suited for windows programming) is lacking in such a major aspect of the C++ paradigm. Humbug. As for the Anonymous Poster''s concern on throwing things often, true, I''m being I guess a bit excessive since error aren''t going to be happening all the time mind you, but right now i have it implemented that macros control if a non-zero HRESULT is passed it throws a specific error based on the error. Nothing special. Quite annoying and slow as Houdini pointed out.

Well, I really do want to continue this thread (and BTW thank you all for your wonderful suggestions), but off an a different tangent. Below are some code snippets from something I mentioned earlier (I really hope I''m not breaking any intellectual property issues here), any ideas on what is going on in the background, how would it be done, since it looks like it''s for an error system:

At the top of this class there''s this little macro, DECLARE_CLASS:

class DLL_EXPORT UD3DRenderDevice : public URenderDevice
{
DECLARE_CLASS(UD3DRenderDevice,URenderDevice,CLASS_Config)

Seems like this macros might be more for debugging purposes, or I might be wrong.

Then scattered around most of the functions are guard() and ungard methods, here''s one example:

void StaticConstructor()
{
guard(UD3DRenderDevice::StaticConstructor);

(all code here)

unguard;
}

Now THIS is exactly what to me would be a perfect error system. 2 lines per function, and then it outputs a wonderful "An error occured in MainLoop->GetFoo->DoFoo->DoMoreFoo->LoadTextures() on line 23 where texture 21 is corrupt" or something like that to a log file or text file, etc.

Any ideas what these functions do, and more importantly, how they work?

Thanks,
Airenthiwan
I have seen many people use the Unreal method of locating errors but frankly I hardly see the point.

Aren''t the __FILE__ and __LINE__ macros all you need?

Besides, clever use of assert''s allows JIT debugging which is even better
-------homepage - email
Advertisement
quote:
Besides, clever use of assert''s allows JIT debugging which is even better


Not in a release build though. And unless your functions are only called from once place a call trace is a lot better than a filename & line number.
(BTW, I was "Anonymous" above)

Check this link to flipcode:
http://www.flipcode.com/cgi-bin/msg.cgi?showThread=Tip-TraceableCallstacks&forum=totd&id=-1

The title is "Traceable Callstacks with C++". It's a tip of the day.

Basically, he tells you exactly what you're asking. To paraphrase:
    #define infunc(func) static const char *__FUNC_NAME__ = #func; try {#define outfunc  } catch (...) { CSAddFunction (__FUNC_NAME__); throw; } 


CSAddFunction adds the current function name to the "call stack", implemented as an STL vector.

Also a lot of good discussion of the pros/cons of this method on that board thread.

try/catch rocks. You should give it a chance.



Edited by - Stoffel on October 1, 2000 9:04:49 PM
Thanks Stoffel,

I''ll look into that URL. You know, I would probably use try/catch blocks now after the good arguments that were posted here on this thread, but sadly MS VC++ 6 doesn''t seem to fully support it.

BTW, anyone knows what exactly isn''t fully support it about it? Is there a way to get around this problem in it? I notice the wearning error pop up as I compile my code..

Aienthiwan
I use VC6 with SP4. It supports try/throw/catch. If you''re getting errors, you might try looking at this menu:

Project->Settings->C/C++->Category "C++ Language"

Make sure "Enable exception handling" is checked.

What VC6 does not support is exception specifications:
void foo () throw (); // foo does not throw exceptions
void bar () throw (X, Y); // bar can throw an X or a Y

According to my C++ ARM (annotated reference manual), "An attempt by a function to throw an exception not in its exception list will cause a call of the function unexpected() ."

This means that if a function throws an exception that it''s not allowed to throw, any exception handler (i.e. catch ()) will be bypassed and the function unexpected() is called. Since this isn''t supported in VC6, programs you compile with it will not bypass the handlers if a differently-specified exception is thrown.

PS: if a function has no exception specification (according to the standard), it may throw any exception.
Advertisement
Ah ok,

If that''s it, it''s alright then. Getting rid of all those throw statements in my header files will get rid of my warnings I''m getting.

Maybe I''m not as sure of myuself after all about try/catch/throws, why am I getting an unhandled exception with this code? Shouldn''t the try block previous to this by catching it?


#include "stdio.h"

void main () {

bool bError = true;
while (bError) {
try {
throw 3.141592F;
} catch (float f) {
printf("An fpu exception occured: %f", f);
throw ''x'';
} catch (char c) {
printf("A char exception occured: %c", c);
bError = false;
}
};
}


Thanks,
Aienthiwan
The reason you are getting the unhandled exception is that your "throw x" line isn''t inside a try block.
- Houdini
[And again I'm beaten because of 20 seconds *sigh*]

Your throw in the catch (float f) { } statement is not in a try block. I know what you want to do, but it doesn't work like that, sorry. If you want to do something like that you need:

        try { // outer try   try { // inner try      throw 2.345f;   }   catch(float f) {      printf("An fpu exception occured: %f", f);      throw 'x';    }}catch (char ch) {   printf("A char exception occured: %c", ch);}        


Edited by - BitMaster on October 2, 2000 4:36:36 PM
Just some ideas about error handling.

try{}catch{} statements are a very good way of dealing with errors that might occur during runtime. Exceptions are perfect for stuff like Networking or reading a file or dealing with hardware that might be plugged out suddenly. Exceptions are not a good way of dealing with errors that might occur when your algorithm isn''t perfect, then you might wan''t some kind of debug/error system that could be deleted for the release version(macro or #ifdef or something).

One idea would be to work with an atomic class, (a class that can return only one instance), then you could have a error counter in that class and a list that you could add to.

of course the add method could easily be implemented to write to a file.

pseudocode:
if(error occur){  errorclass.getInstance().add("problem in function foo bla... bla...);} 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~I'm looking for work

This topic is closed to new replies.

Advertisement