Compared with the stimulus abort () and exit (), the goto statement seems to be a more feasible solution to handle exceptions. Unfortunately, goto is local: it can only jump to the internal label of the function, but cannot transfer control to any location of the Program (of course, unless all your code is in the main body ).
To solve this problem, the C function library provides setjmp () and longjmp () functions, which are used for non-local labels and goto functions. The header file <setjmp. h> declares these functions and the jmp_buf data types required at the same time.
Setjmp. h is the header file that provides "non-local jump" in the C standard function library: the control flow deviates from the usual subroutine call and return serial. The two complementary functions setjmp and longjmp provide this function.
The typical purpose of setjmp/longjmp is to implement an exception handling mechanism: Use longjmp to restore the state of a program or thread, or even skip multi-layer function calls in the stack.
Setjmp stores the current environment (that is, the state of the program) to a platform-related data structure (jmp_buf ), this data structure can be used by longjmp to restore the state of the program to the original state when the setjmp call is saved to jmp_buf. This process can be considered as "jump" back to the execution status of the program saved by setjmp. The return value of setjmp indicates whether the control is normal to reach the point or is restored by calling longjmp.
The principle is very simple:
1. setjmp (j) sets the "jump" point and fills in jmp_buf object j with the correct program context. This context includes the location, stack, framework pointer, other important registers, and memory data of the program. After jump is initialized, setjmp () returns 0.
2. the effect of calling longjmp (j, r) later is that a non-local goto or "Long Jump" is directed to the context described by j (that is, to the setjmp () of the originally set j () ). When called as a long jump target, setjmp () returns r or 1 (if r is set to 0 ). (Remember, setjmp () cannot return 0 in this case .)
Jmp_buf array type, such as struct int [16] or struct _ jmp_buf_tag, used to save the information required to restore the CALL Environment
There are two types of return values. setjmp () lets you know how it is being used. When j is set, setjmp () is executed as expected; but when it is used as a long jump target, setjmp () will "wake up" its context from the outside. You can use longjmp () to terminate an exception and use setjmp () to mark the exception handling program.
# Include <setjmp. h>
# Include <stdio. h>
Jmp_buf j;
Void raise_exception (void)
{
Printf ("exception raised \ n ");
Longjmp (j, 1);/* jump to exception handler */
Printf ("this line shoshould never appear \ n ");
}
Int main (void)
{
If (setjmp (j) = 0)
{
Printf ("\ ''setjmp \'' is initializing \ ''j \ ''\ n ");
Raise_exception ();
Printf ("this line shoshould never appear \ n ");
}
Else
{
Printf ("''setjmp'' was just jumped into \ n ");
/* This code is the exception handler */
}
Return 0;
}
/* When run yields:
''Setjmp'' is initializing ''j''
Exception raised
''Setjmp'' was just jumped
*/
The function filled with jmp_buf is not returned before longjmp () is called. Otherwise, the context stored in jmp_buf has a problem:
Jmp_buf j;
Void f (void)
{
Setjmp (j );
}
Int main (void)
{
F ();
Longjmp (j, 1);/* logic error */
Return 0;
}
Therefore, you must process setjmp () as a non-local jump to its location.
Longjmp () and setjmp () Federated run in Stages 2 and 3 of the abnormal life cycle. Longjmp (j, r) generates the exception object r (an integer) and transmits it to setjmp (j) as the return value. In fact, the setjmp () function reports the exception r.
The following example uses a switch to better display the functions of this function:
# Include <setjmp. h>
# Include <stdio. h>
Jmp_buf j;
Void raise_exception (void)
{
Printf ("exception raised \ n ");
Longjmp (j, 3);/* jump to exception handler case 3 */
Printf ("this line shoshould never appear \ n ");
}
Int main (void)
{
Switch (setjmp (j ))
{
Case 0:
Printf ("''setjmp'' is initializing ''j'' \ n ");
Raise_exception ();
Printf ("this line shoshould never appear \ n ");
Case 1:
Printf ("Case 1 \ n"); break;
Case 2:
Printf ("Case 2 \ n"); break;
Case 3:
Printf ("Case 3 \ n"); break;
Default:
Break;
}
Return 0;
}