Exception handling in C

technicalBefore proceeding, let’s understand the difference between error handling and exception handling. Programming languages like C++ and JAVA provide in-built support for exception handling which boils down most of the time to normal error handling under language wrap-ups. For example, user-defined exceptions thrown in JAVA functions can be translated directly into returning a pre-defined error code from callee and handing that in the caller function. The JAVA framework has robust features like stack-trace, messages etc. but that will be deemed cosmetic to a seasoned C developer (and equivalent information can be achieved using siginfo_t and ucontext_t). For errors like buffer overflow (which is an error) the responsibility is on the C programmer to handle it. Exceptions are actually thrown by the CPU (and not your code) when it detects issues at runtime e.g. floating point exception or division by zero etc. They can be handled as elegantly in C using signal handlers as they are handled in any other programming language.

The following program illustrates handling signals raised by the programmer (greatly useful in multi-threaded programs) as well as CPU exceptions in C. I have added some casual comments to explain the flow and omitted return value checks for signal(), sigaction() etc. as well. For serious information check the man page for signal (7), sigaction.

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>

void mySIGTERMHandler(int signum)
{
    printf("Received SIGTERM!\n");
}

void mySIGSEGVHandler(int signum)
{
    printf("Received SIGSEGV!\n");
    raise(SIGTERM); //just for fun, call user defined handler
    raise(SIGABRT); //same as abort(), unhandled
}

int main()
{
    int retval = 0;
    struct sigaction sigact;
    int* ptr = NULL;

    signal(SIGTERM, mySIGTERMHandler); //register handler. old school, use sigaction
    retval = kill(getpid(), SIGTERM); //same as raise(SIGTERM);
    printf("kill returned: %d\n", retval);

    memset(&sigact, 0, sizeof(struct sigaction));
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = SA_RESETHAND; //once the defined handler is called, handler is set to default
    sigact.sa_handler = mySIGSEGVHandler;
    sigaction(SIGSEGV,&sigact,NULL); //register handler

    *ptr = 'a'; //leads to an exception, SIGSEGV thrown

    printf("before return\n");
    return 0;
}

OUTPUT:

Received SIGTERM!
kill returned: 0
Received SIGSEGV!
Received SIGTERM!
Aborted

Update:

As signals are rather primitive, the setjmp() and longjmp() combination is a better way of handling exceptions in C as Falls has pointed out in his comment. Ref: Exception Handling in C without C++

2 thoughts on “Exception handling in C”

Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s