📜 ⬆️ ⬇️

Implementation of the exception mechanism using the C language

C ++, Java, C # programmers ... when writing code on "pure" C, often face the problem of the absence of an exclusion mechanism. The classic way to handle errors in C is to check return codes. In complex algorithms with deep nesting it is very inconvenient. The method given below is not new, but, unfortunately, many are not familiar with it.

So, in POSIX there are a couple of useful functions: setjmp and longjmp

 #include <setjmp.h>

 int setjmp (jmp_buf env);
 void longjmp (jmp_buf evn, int val);

')
Consider an example:

 #include <setjmp.h>
 jmp_buf jbuf;

 / * ...... * /

 / * Install handler * /
 int result = setjmp (jbuf);
 switch (result) {
    case 0: / * this is a try block * /
    case 1: / * One of the catch blocks * /
    case 2: / * Another catch * /
 };

 / * .... * /

 / * Here we want to throw an exception * /
 longjmp (jbuf, DISCOUNT CODE);


A call to setjmp saves the state of the stack to a variable. When you save, setjmp returns 0. This variable must be made available to the code that will initiate the transition. After the longjmp output, everything will look as if setjmp returned a value other than 0.

What is worth noting:
1) longjmp never returns. Either there will be a rollback to setjmp, or if the jmp_buf is broken - the segmentation fault.
2) The second parameter of longjmp is the value that setjmp will return when the stack is restored. 0 transfer fails (in this case, returns 1).
3) The mechanism described above breaks the "normal logic" of the program's work on C. In this case, in some cases it can make the program more readable. This should be treated as goto.

UPDATE note from mraleph:
Strictly speaking, setjmp does not save “stack state”. It stores only the values ​​of the registers, so in particular jmp_buf can not be used if the function in which it was created has ended ...

Source: https://habr.com/ru/post/50985/


All Articles