Monday, January 24, 2011

What is Setjmp and longjmp In C/C++?




These two functions are not only supported in Unix, but also used extensively in both DOS and Windows. They are a pair of instructions that can be used as a simple mechanism to quit a process. An example would be this: Consider that you have a main control function that calls other functions, and these other functions call other functions to a relatively large depth. You test for various "critical errors" in your deepest code - these are errors that cause you to stop processing the current task. Without using setjmp/longjmp, if you encountered an error in the lowest level of functions, you would have to set some flag, and return it to the calling function. This returning function would have to check this flag, and return it to its calling function, and continue up the call tree to the main control function, who would also have to check the return flag and act on the information. With setjmp/longjmp, you simply call setjmp in the main control function, and when you detect the error in the low-level function, you just call longjmp. This effectively returns directly to the main control function without having to test for error conditions within the intermediate functions. The stack will be corrected to point where your program will be able to continue execution. It is effectively a "goto" command directly from your longjmp command directly back to you setjmp command. There is a downside to this - it your intermediate functions use any temporary resources, such as allocating memory or opening files, setjmp/longjmp will not release these resources, so you have to be very careful with your design when using these. C++ has addressed this problem with its exception handling capabilities, which is far superior to using setjmp/longjmp.

In Short, a typical use of setjmp/longjmp is implementation of an exception mechanism that utilizes the ability of longjmp to reestablish program state, even across multiple levels of function calls.

Simple Example is mentioned as below:-


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;
}

Output of the above program as mentioned is:-

second
main


No comments:

Post a Comment