[OT] - C++ exceptions are becoming more and more problematic

H. S. Teoh hsteoh at quickfur.ath.cx
Thu Feb 24 20:01:20 UTC 2022


On Thu, Feb 24, 2022 at 11:14:39AM -0800, Walter Bright via Digitalmars-d wrote:
> On 2/23/2022 11:23 PM, rikki cattermole wrote:
> > 
> > On 24/02/2022 6:05 PM, Walter Bright wrote:
> > > One of the requirements I proposed for Phobos2 was for it to not
> > > use exceptions.
> > 
> > This is the sort of code we are going to end up with without a
> > solution like value type exceptions. Explicit error types and
> > returns ala @mustuse are not better than runtime exceptions, they
> > are much worse for readability.
> 
> I agree, which makes this a challenge.
> 
> One solution is to design the return value so that failure is a valid
> part of the type. For example, searching for X can return an empty
> result, rather than a special "not found" error.
[...]

The problem with replacing exceptions with return codes is that it
requires writing tons of boilerplate to handle error codes. I work with
C at work every day, and eventually every function starts looking like
this:

	int some_func(some_type_t *some_args) {
		int ret = SOME_FUNC_ERR;

		if ((ret = do_something(...)) != DO_SOMETHING_OK)
			goto EXIT;

		if ((ret = do_something_else(...)) != DO_SOMETHING_ELSE_OK)
			goto EXIT;

		if ((ret = do_yet_another(...)) != DO_YET_ANOTHER_OK)
			goto EXIT;

		// ... ad nauseaum

		ret = SOME_FUNC_OK;
	EXIT:
		return ret;
	}

Every single function call must be wrapped with `if ((ret = blah(bleh))
== bluh)` boilerplate, and every developer on the team inevitably
reinvents their own system of error codes, so you have 1001 different
representations of success and failure, and woe to you when you mix up
one for the other because you'd have silently introduced a subtle bug.

And of course, given the painful amounts of boilerplate involved, people
tend to get lazy so error codes are not checked, or don't get propagated
correctly, etc..

Not to mention the proliferation of thrice-reinvented gratuitously
incompatible lists of error codes across every module, and sometimes
every function. Once you go past 1 or 2 levels in the call graph, the
fine distinctions between these error codes get lost in translation,
with the inevitable result that nobody uses any of the error codes
except for "OK" and "INTERNAL_ERROR".  Every single possible failure in
a complex subsystem of 26-level deep function calls eventually collapses
onto a generic, useless "INTERNAL_ERROR", and good luck to the poor fool
who has to debug where in the 50 or so files the problem is when the
customer reports that the application said "internal error".


This is NOT where I want D to go.  Getting rid of exceptions is a
non-solution, we're just going back to the bad ole days of manual error
checking, gratuitous boilerplate, and incentivizing programmers to
ignore / shove aside errors as much as possible 'cos error handling just
Gets In The Way(tm).

What we should be doing instead is, free ourselves from the needless
constraints of C++ exception handling, and implement a better mechanism
for throwing exceptions. Leave C++ interop at the C++/D boundary;
extern(D) code ought to be able to throw away libunwind and use a much
more efficient implementation of exceptions than C++ does.


T

-- 
Latin's a dead language, as dead as can be; it killed off all the Romans, and now it's killing me! -- Schoolboy


More information about the Digitalmars-d mailing list