February 4, 2008
I was pretty interested by this blog post, because that’s something I have been pretty annoyed with lately.
I’m not discussing just g_malloc and OOM issues there, but more generally error handling. There are several ways to deal with them, but they mostly all fall short somewhere.
There is a first scheme, let’s call it the GError scheme, which looks like this:
result = do_foo (arg1, …, argN, &error);
this is pretty nice, and can allow displaying errors to the user pretty readily, but the error is generally a complex type, so one has to some code to write them, and using them isn’t straightforward. For example, you generally see in the api that you’re getting an error, but not exactly which…
There is a second, which I don’t exactly know how to name, and which looks like this:
error = do_foo (arg1, …, argN, &result);
that one I find nicer : generally the error isn’t some complex type, but an enumeration, with an ALL_OK somewhere and a few ERROR_FOO, ERROR_BAR, etc — so you really know what you’re getting, and you have a real chance to be able to deal with it.
A third scheme requires the result to have special types — special in that there are error cases embedded in them. Typical examples are functions which return a NULL pointer on error, or how cairo does things, with a more general error handling (basically, the result object has some kind of get_error_condition which gives something like the enum of the second scheme). That is pretty much the best option in my opinion, even if that cannot always be readily done.
Finally, there are exceptions, which are pretty special in that a few languages have special support for them. I find them the worse of the lot. They’re much like the first scheme : they’re generally complex types. But they don’t even have the decency to turn up in the api, even in otherwise sane languages! For example, even in a language like Ocaml, you end up with :
– : (‘a -> bool) -> ‘a list -> ‘a =
# List.find (fun a -> (a=2)) [1;3;5];;
Gasp! I was promised a function with an api, and the exception wasn’t even visible! That is already pretty bad in Ocaml where you don’t manage memory, but reading any C++ documentation about how to handle exceptions and avoid leaks is… a very interesting read, in a way.