Implementing exceptions in C


After reading about the PS Vita webkit exploit, I discovered the standard C functions: setjmp and longjmp, found in setjmp.h.

To understand what these functions do, take a look at the following example:

The example below shows the basic idea of setjmp. There, main() calls first(), which in turn calls second(). Then, second() jumps back into main(), skipping first()'s call of printf().

#include <stdio.h>
#include <setjmp.h>
 
static jmp_buf buf;
 
void second(void) {
    printf("second\n");         // prints
    longjmp(buf,1);             // jumps back to where setjmp was called - making setjmp now return 1
}
 
void first(void) {
    second();
    printf("first\n");          // does not print
}
 
int main() {   
    if ( ! setjmp(buf) ) {
        first();                // when executed, setjmp returns 0
    } else {                    // when longjmp jumps back, setjmp returns 1
        printf("main\n");       // prints
    }
 
    return 0;
}

When executed, the above program will output:

second
main

Notice that although the first() subroutine gets called, "first" is never printed. "main" gets printed as the conditional statement if ( ! setjmp(buf) ) is executed a second time.



As you can see, this is not very maintainable code. It is also common for there to be differences between different implementations of the functions, making it something that you should avoid using.

What practical use could these functions ever have? Well, Wikipedia states that:

A typical use of setjmp/longjmp is implementation of an exception mechanism


So, I decided to see if I could get an exception handling implementation of my own, in C.

The library I wrote can be found on GitHub, it is used like so:

/*
	Program output:

	Doing something...
	Process failed due to error 1!
	End of program
*/

#include <stdio.h>

#include "exception.h"

void process(void) {
	printf("Doing something...\n");
	throw(1);
}

int main(void) {
	// Create a new exception
	exception(
		try() {
			process();
			
			// this never happens because process always throws error 1
			printf("Got to end of process!\n");
		}
		
		// is executed when throw(1) is called within the try
		catch(1) {
			printf("Process failed due to error 1!\n");
		}
		
		// is executed when a throw is called within the try and there
		// is no catch specific to the exception
		finally() {
			// use e to get the value passed to throw
			printf("Process failed due to error %d!\n", e);
		}
	);
	
	printf("End of program\n");
	
	return 0;
}

As you can see, the syntax is at least a little bit cleaner than using setjmp and longjmp directly, but I would still not recommend using this in any serious projects.