# C Programming/Error handling

C does not provide direct support for error handling (also known as
exception handling). By convention, the programmer is expected to
prevent errors from occurring in the first place, and test return values
from functions. For example, -1 and NULL are used in several functions
such as socket() (Unix socket programming) or malloc() respectively to
indicate problems that the programmer should be aware about. In a worst
case scenario where there is an unavoidable error and no way to recover
from it, a C programmer usually tries to log the error and
\"gracefully\" terminate the program.

There is an external variable called \"errno\", accessible by the
programs after including \<errno.h\> - that file comes from the
definition of the possible errors that can occur in some Operating
Systems (e.g. Linux - in this case, the definition is in
include/asm-generic/errno.h) when programs ask for resources. Such
variable indexes error descriptions accessible by the function
\'strerror( errno )\'.

The following code tests the return value from the library function
malloc to see if dynamic memory allocation completed properly:

``` c
#include <stdio.h>        /* perror */
#include <errno.h>        /* errno */
#include <stdlib.h>       /* malloc, free, exit */

int main(void)
{

    /* Pointer to char, requesting dynamic allocation of 2,000,000,000
     * storage elements (declared as an integer constant of type
     * unsigned long int). (If your system has less than 2 GB of memory
     * available, then this call to malloc will fail.)
     */
    char *ptr = malloc(2000000000UL);

    if (ptr == NULL) {
        perror("malloc failed");
        /* here you might want to exit the program or compensate
           for that you don't have 2GB available
         */
    } else {
        /* The rest of the code hereafter can assume that 2,000,000,000
         * chars were successfully allocated... 
         */
        free(ptr);
    }

    exit(EXIT_SUCCESS); /* exiting program */
}
```

The code snippet above shows the use of the return value of the library
function malloc to check for errors. Many library functions have return
values that flag errors, and thus should be checked by the astute
programmer. In the snippet above, a NULL pointer returned from malloc
signals an error in allocation, so the program exits. In more
complicated implementations, the program might try to handle the error
and try to recover from the failed memory allocation.

## Preventing divide by zero errors

A common pitfall made by C programmers is not checking if a divisor is
zero before a division command. The following code will produce a
runtime error and in most cases, exit.

``` c
int dividend = 50;
int divisor = 0;
int quotient;

quotient = (dividend/divisor); /* This will produce a runtime error! */
```

In ordinary arithmetic division by zero
is undefined. Because of this, you must check or make sure that a
divisor is never zero. Alternatively, for \*nix processes, you can stop
the OS from terminating your process by blocking the SIGFPE signal.

The code below fixes this by checking if the divisor is zero before
dividing.

``` c
#include <stdio.h> /* for fprintf and stderr */
#include <stdlib.h> /* for exit */
int main( void )
{
    int dividend = 50;
    int divisor = 0;
    int quotient;

    if (divisor == 0) {
        /* Example handling of this error. Writing a message to stderr, and
         * exiting with failure.
         */
        fprintf(stderr, "Division by zero! Aborting...\n");
        exit(EXIT_FAILURE); /* indicate failure.*/
    }

    quotient = dividend / divisor;
    exit(EXIT_SUCCESS); /* indicate success.*/
}
```

## Signals

In some cases, the environment may respond to a programming error in C
by raising a signal. Signals are events raised by the host environment
or operating system to indicate that a specific error or critical event
has occurred (e.g. a division by zero, interrupt, and so on.) However,
these signals are not meant to be used as a means of error catching;
they usually indicate a critical event that will interfere with normal
program flow.

To handle signals, a program needs to use the `signal.h` header file. A
signal handler will need to be defined, and the signal() function is
then called to allow the given signal to be handled. Some signals that
are raised to an exception within your code (e.g. a division by zero)
are unlikely to allow your program to recover. These signal handlers
will be required to instead ensure that some resources are properly
cleaned up before the program terminates.

The C Standard Library only defines six signals; Unix systems define 15
more. Each signal has a number, called a signum, associated with it.
Here are a few common ones:

``` c
    #define SIGHUP  1   /* Hangup the process */ 
    #define SIGINT  2   /* Interrupt the process. C standard */ 
    #define SIGQUIT 3   /* Quit the process */ 
    #define SIGILL  4   /* Illegal instruction. C standard.*/ 
    #define SIGTRAP 5   /* Trace trap, for debugging. C standard.*/ 
    #define SIGABRT 6   /* Abort. C standard. */
    #define SIGFPE  8   /* Floating Point Error. C standard. */
    #define SIGSEGV 11  /* Memory error. C standard.  */
    #define SIGTERM 15  /* Termination request. C standard. */
```

Signals are handled with the `signal()` function, from the `signal.h`
library. Its syntax is:

``` c
void signal(signal_to_catch, signal_handler)
```

Signals can be raised with `raise()` or `kill()`. `raise()` sends the
signal to the current process; `kill()` sends it to a specific process.

*Note that `signal` is now deprecated in favor of `sigaction()`, due to
a lack of portability between Unix systems and potential for unexpected
behavior. However, as `sigaction()`\'s use is more complicated, we will
stick with `signal()` to illustrate the concept here.*

To understand how signals work, here\'s a simple example:

``` c
#include <stdio.h>
#include <unistd.h> // Unix Standard library, used to import sleep()
#include <stdlib.h>
#include <signal.h>

void handler(int signum) {
   printf("Signal received %d, coming out...\n", signum);
   exit(1);
}


int main () {
   signal(SIGINT, handler); // attaching the handler() function to SIGINT signals; i.e, ctrl+c, keyboard interrupt.

   while(1) {
      printf("Sleeping...\n");
      sleep(1000); // sleep pauses the process for a given number of seconds, or until a signal is received. 
   }
   return(0);
}
```

Try compiling and testing this on your machine; after you see
\"Sleeping\...\", send the interrupt signal by pressing `ctrl + c`.

Here\'s a more complex example. This creates a signal handler and raises
the signal:

``` c
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

static void catch_function(int signal) {
    puts("Interactive attention signal caught.");
}

int main(void) {
    if (signal(SIGINT, catch_function) == SIG_ERR) {
        fputs("An error occurred while setting a signal handler.\n", stderr);
        return EXIT_FAILURE;
    }
    puts("Raising the interactive attention signal.");
    if (raise(SIGINT) != 0) {
        fputs("Error raising the signal.\n", stderr);
        return EXIT_FAILURE;
    }
    puts("Exiting.");
    return 0;
}
```

## setjmp

The setjmp function can be
used to emulate the exception handling feature of other programming
languages. The first call to setjmp stores a reference point to the
current execution point, and is valid as long as the function containing
setjmp() doesn\'t return or exit. A call to longjmp causes the execution
to return to the point of the associated setjmp call.

`setjmp` takes a \`jmp_buf\` (a type that will store an execution
context) as an argument, and returns `0` the first time it runs (i.e.,
when it sets the return point). When it runs a second time - when
`longjmp` is called - it then returns the value passed to `longjmp`.

`longjmp` takes a \`jmp_buf\` as an argument (one that\'s already been
passed to `setjmp`), and a value to pass to `setjmp` to return.

``` c
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>

int main(void) {
   int val;
   jmp_buf environment;

   val = setjmp(environment); // val is set to 0 the first time this is called

   if (val !=0) 
   {
      printf("You returned from a longjmp call, return value is %d", val); // now, value is 1, passed from longjmp()
      exit(0);
   }

   puts("Calling longjmp now");
   longjmp(environment, 1);

   return(0);
}
```

Try running this with a compiler on your own machine.

The values of non-volatile variables may be corrupted when setjmp
returns from a longjmp call.

While setjmp() and longjmp() may be used for error handling, it is
generally preferred to use the return value of a function to indicate an
error, if possible. setjmp() and longjmp() are most useful when errors
occur in deeply nested function calls, and it would be tedious to check
return values all the way back to the point you wish to return to.

