Sunday, April 19, 2009

Suneido Exception Handling part 2

It actually didn't take that long to implement the ideas I talked about in my last post.

I ran into some problems with circular dependencies when I made my exceptions derive from SuString, but by splitting the header I got around these.

The hardest part was remembering how C++ exceptions work. A year of programming mostly in Java and already the C++ details are fading!

I remembered something in Effective C++ but it turned out to be in More Effective C++.

The recommended style is:
throw MyException(...)

...

catch (const MyException& e)
At first glance this seems wrong because you're throwing a temporary value, but C++ copies thrown exceptions. And catching by reference avoids a second copy that's done if you catch by value.

Of course, this recommendation assumes no garbage collection. With garbage collection, like in Suneido, it's reasonable to just throw and catch pointers, which is what I ended up doing. (Before changing to pointers I ran into problems because I passed the caught exception to the Suneido catch code, forgetting that the caught value is a temporary on the stack.)

It was a good reminder of the extra complexity in C++. In Java you don't have to worry about whether you have a value or a pointer or a reference and whether it's on the stack or the heap. You do have the difference between primitive types and reference types, but especially with auto-boxing and un-boxing it's pretty transparent. And in any case, it doesn't lead to crashes like forgetting a C++ value is on the stack.

Since exceptions are a sub-class of strings, all the existing code that assumes strings works fine.

I added two methods: exception.As(newString) to re-throw an exception with a different string. And exception.Callstack() to retrieve the call stack from an exception (e.g. to log it).

Next, I'll have to go through our libraries and make sure that any re-throws are done properly to preserve the original source of the exception, and that any logging uses the callstack from the exception.

No comments: