

Emulating exceptions in C: a case study - sevko
http://sevko.io/articles/exceptions-in-c/

======
itsuart
I think exceptions are very bad idea. Not nearly as bad as implicit
nullability but comparable. Hacky emulations of exceptions... Well I don't
want to be near such code.

But that was interesting read non the less, thanks OP.

~~~
markbnj
I agree it was an interesting read. Haven't thought about setjmp and longjmp
in many years.

>> I think exceptions are very bad idea.

There are many cases, API implementations for example, where I cannot think of
a better solution. Packing result codes into returned data, using return
values, using global state, using passed state buffers, all those approaches
are worse, imo, and lead to less readable and maintainable code. What's your
preferred alternative?

~~~
itsuart
In Haskell I use Maybe's, Either's and their ilk (packing result code in
returned data I guess?), in C - your usual boolean return values like this:
bool parse_literal (ParsingState* state, LiteralValue* pResult).

In Java/C# I have to use what other people are using :)

My dislike of exceptions (as well as errno and Set/GetLastError) is due their
masking, hiding error conditions and situations. And I prefer everything to be
stated clearly. Including error handling code (answer to 'did I handled all
possible failures of calling this?' should be instant).

Unfortunately proper error handling is hard, nearly as much as 'naming things'
:)

------
zvrba
> longjmp() and setjmp() are tricky. They’re obscure, can give rise to subtle
> bugs, are highly platform-specific, and, if abused, will probably lead to
> awfully confusing code

Actually, being part of the ISO C standard, they are _not_ platform-specific.
Otherwise, just use C++ where destructors take care of cleanup when an
exception is thrown.

~~~
pjmlp
> Actually, being part of the ISO C standard, they are not platform-specific.

The standard doesn't define the full semantics, specially what happens when a
signal, trap, OS exception and similar occurs.

------
Animats
This is like an article on how to use a screwdriver as a chisel.

~~~
kwhitefoot
If you need a chisel but only have a screwdriver then advice on how to best
use it sounds valuable to me.

~~~
Animats
Everybody has access to C++ now. Even on the Arduino. If you need exceptions,
go to C++. "longjmp" was a bad idea when it was first invented, and it hasn't
improved with age.

~~~
stinos
Yet whole applications are written around it and they work perfectly well. Not
saying that is an argument that it is somehow a good idea, just that while it
might looks bad, it also works ok when done properly.

~~~
humanrebar
> it also works ok when done properly

That's circular reasoning. The objection is that it only works well in certain
circumstances. Mostly in fairly simple applications with either small teams or
rigid conventions to enforce clarity and prevent bugs.

~~~
tiagobraw
Well, Lua coroutines uses longjmp and they're not "fairly simple" in any way.

I don't think it is a circular reasoning. There's always the good and the bad
way to use something, even C++ exceptions.

~~~
humanrebar
If "done properly" implies "works ok", then it's circular reasoning.

I'm not sure your example is a counterexample either. Implementing part of a
fairly simple runtime (like Lua's) using longjmp is an example of a good use
of longjmp, in my opinion.

------
reifnir
Easiest way to emulate Exceptions: just use a GOTO statement.
[http://c2.com/cgi/wiki?DontUseExceptionsForFlowControl](http://c2.com/cgi/wiki?DontUseExceptionsForFlowControl)
[http://www.joelonsoftware.com/items/2003/10/13.html](http://www.joelonsoftware.com/items/2003/10/13.html)

------
Murk
When I went for a job interview at Symbian many years ago for a position
working on Symbian OS, they told me (and it's obvious from looking at their
documentation) that they implemented thier own execption mechanism in C++
using setjmp and longjmp becuase they deemed that the C++ execption system was
too slow. Other accounts say that the exception mechanism wasn't present in
the language at the time, which I am not sure of.

This is why you had to push all local variables onto a clearnup list in each
an every function, this I think, from memory was a call to CleanupStack::Push
with a wrapper macro.

If indeed they did this becuase exxceptions were 'too slow', then the problem,
im my option would be that they were using exceptions far too much -- as
status indications and so on. They are, again, in my option a great help used
in the right way, with the C++ RAII idiom, which is essential in the face of
exceptions.

------
_RPM
I actually wrote a JSON parser for fun and profit 2 weeks ago. It's mind
blowing to me how his code is similar to mine. I wrote mine completely from
scratch. I even called my routine `parseValue`. Once one has a look at the
JSON grammar, writing a parser for it is trivial.

------
halayli
Exceptions are not about going from one place to another. It's about unwinding
the stack properly and calling the destructors of variables on the stack. This
is not a close emulation at all.

~~~
rwmj
While I'm not saying this is a good idea, you can combine a pool allocator
with longjmp exceptions to get an approximation of unwinding. It requires that
you are very careful about structuring your code, but I once wrote a whole web
server this way:
[http://git.annexia.org/?p=rws.git;a=tree](http://git.annexia.org/?p=rws.git;a=tree)
(using:
[http://git.annexia.org/?p=c2lib.git;a=tree](http://git.annexia.org/?p=c2lib.git;a=tree)
).

~~~
halayli
But sometimes it's not just memory. It can be files you need to close, or any
other resource held.

~~~
chaz72
That too can be queued up, with a list of functions to call to free those
resources.

~~~
halayli
He was referring to a memory pool allocator. But regardless, good luck with
the approach.

------
alexknvl
Let me use my favourite tool of intellectual terrorism: Just use monads. Ouch,
now we have two problems here. :P

~~~
vog
To be serious: This was my first thought, too. Exceptions are essentially one
kind of monads, and any complex compiler or interpreter could make good use of
more types of monads.

I believe the paper of Wadler makes this most clear. Some time ago, it was a
real eye-opener for me:

[http://homepages.inf.ed.ac.uk/wadler/papers/essence/essence....](http://homepages.inf.ed.ac.uk/wadler/papers/essence/essence.ps)

