Bringing try catch blocks to C
Filed under C, How-to, Programming.
Viewed 1241 times times.
Error handling in C is never an easy task. Pretty much any function can return an error, and if you really want to have stable and bug free code, you must be able to handle them. The problem, of course, is that having to always check for errors quickly leads to bloated ugly code.
C++, Java and other higher level languages have solved this by introducing Exceptions and try-catch blocks. The idea is simple, when something goes wrong, a function or method “throws” an exception to signal the error. The try block is used around a piece of code where the programmer anticipates that something might go wrong (reading user input, opening files, etc…) and every exception thrown inside the try block is then “caught” in the catch block that normally follows “try”.
Luckily, there is an easy way of reproducing this behavior in everybody’s favorite lower level programming language. For a try block we will be using:
do{ //Error prone code }while(0);
This pattern has two advantages, it executes the code inside it exactly once, and it gives us an easy way of getting out of it using break; when something unexpected happens. Now all we have to do, if an error occurred, is to set a flag, and break out of the “loop”.
The “catch block” is simply an if block that checks if the error flag has been set and handles the error accordingly. Using these two constructs, we have managed to isolate the code from the error handling.
Unfortunately, we must still check for the errors within the try block, but we can reduce the ugliness of this part as well. We define a macro that abstracts away checking for an error, setting the flag and breaking out:
#define ERR(cond,value) {if(cond){error=value; break;}}Where error is an unsigned declared outside the try block that is used to signal which error occurred. You can think of it as a poor-man’s exception. Using a macro in this context has one other advantage. It gives us the ability to completely eliminate error checking at compile time. This can be useful if performance is of the essence and we are confident that everything will go well. A simple function that exemplifies these constructs is shown below. As always, I would like to hear any comments or suggestions you might have.
#ifdef NOERRCHECK #define ERR(cond,value) #else #define ERR(cond,value) {if(cond){error=value; break;}} #endif unsigned piped(char command[],char fin[],char mode[]) { char *file; FILE *fp; int in=-1; //The error that occured. 0 means everything is fine. unsigned error=0; //Try Block do{ int size=strlen(fin)+strlen(command)+4; file=malloc(sizeof(char)*size); ERR(file==NULL,1); size=snprintf(file,size,"%s \"%s\"",command,fin); ERR(size!=strlen(file),2); fp=popen(file,mode); ERR(fp==NULL,3); free(file); in=fileno(fp); ERR(in<0,4); }while(0); //Catch block if(error!=0) { perror("piped"); } return in; }

Blog Index
Subscribe via Email

October 19th, 2007 at 4:23 pm
Misleading. You neither describe exceptions nor try-catch blocks in C.
October 19th, 2007 at 5:08 pm
I explain how to create a similar mechanism in C, despite the lack of Classes or any OOP concepts. The fact that I use a macro as a form of throwing the “exceptions” gives the added advantage that you can completely turn off error checking at compile time if you choose to do so.
Of course, there are limitation to this approach… namely, my “exceptions” can’t propagate up the stack. I believe this is a limitation of C for which there is no work around. If you know one, I would very much like to hear it.
If you want something even closer to the way try-catch blocks are normally used you can do:
December 14th, 2007 at 7:04 pm
Should I start with C or C++?
Exception errors are a good way to learn a new language, as I found with VB.NET.