C++ exceptions and CartoType

I've recently changed the way CartoType handles errors by moving from error codes to exceptions in the core library, which is written in C++. Don't worry! The API remains the same and returns error codes where needed. Public functions catch exceptions and convert them to error codes. The change is now stable and has been released as part of CartoType 7.0. Internally thousands of error checks have been removed, speeding up and simplifying the code, and as a useful by-product I've been able to fix a number of bugs.

Before embarking on this slightly risky voyage I did a fair amount of research to verify that the cost would be acceptable. It turns out that everything is fine: there is no measurable cost as long as the normal path of execution doesn't throw exceptions. This confirms the adage that exceptions should not be used as a new control flow construct or a way to return ordinary results. In fact they should be used only in exceptional circumstances; the clue is in the name. In CartoType an exception might be thrown when a data file suddenly can't be read (perhaps someone pulled a USB stick out) or a map projection is given absurd coordinates, or an XML style sheet contains a syntax error. In the ordinary flow of control these things don't happen. Using exceptions creates an uncluttered and readable 'good path', with a hidden 'bad path' that magically cleans everything up and passes control right back up the stack to a handler.

Exceptions are much easier to use in modern C++, for one reason: everything can have an owner. By which I mean that every local variable can easily be created from standard library components which manage memory correctly: their destructors clean up after them, in particular by freeing everything they allocate on the heap. The standard aggregate and smart pointer classes are your friends. Except in very special circumstances, which need to be re-examined every now and then and re-justified, naked new and delete should never be seen. So when an exception is thrown, the exception system can call destructors for every live object all the way up the stack and there won't be any memory leaks. Luckily I moved to modern C++ for CartoType some time ago: initially C++11; now C++14; I have to be a little cautious because CartoType runs on so many platforms, but I hope to move everything to C++17 soon.

When are you planning on a Rust refactoring? ;-)

Like
Reply

Good to hear someone refactoring their codebase like this. Not a small amount of analysis and work I imagine. We used to have quite fierce debates on the use of exception handling with some liking to use it for day to day control flow. Agree that the key is the name ..... You can tell which side of the argument I found myself on. I would hope that most mature C++ development teams have a wiki with their coding standard set out and that this includes :-) the MO for exception handling patterns.

To view or add a comment, sign in

More articles by Graham Asher

Others also viewed

Explore content categories