Paste to learn more about the use of setjmp and longjmp

Source: Internet
Author: User
In the previous article, I had a comprehensive understanding of setjmp and longjmp functions, especially the functions of these two functions, the functions completed by the functions, and the combination of setjmp and longjmp functions, the execution process of the control flow of the program module when exception handling is implemented. Here we will go further and give a very comprehensive explanation of the specific use methods and application scenarios of setjmp and longjmp.

Note that setjmp and longjmp functions are always used in combination. They are closely related operations. Only by combining them can the control flow of programs be effectively transferred, only in accordance with the programmer's pre-designed intent, to achieve the possible exceptions in the program for centralized processing.

Similar to the GOTO statement, it can achieve local jump

This is easy to understand, but I 'd like to list a sample program! As follows:

Void main (void)
{
Int jmpret;

Jmpret = setjmp (Mark );
If (jmpret = 0)
{
// Execute other code
// Determine whether an error occurs in the program's remote connection. If an error exists, it will jump!
If (1) longjmp (mark, 1 );

// Execute other code
// Determine whether an error occurs in the program's remote connection. If an error exists, it will jump!
If (2) longjmp (mark, 2 );

// Execute other code
// Determine whether an error occurs in the program's remote connection. If an error exists, it will jump!
If (-1) longjmp (mark,-1 );

// Execute other code
}
Else
{
// Error Handling Module
Switch (jmpret)
{
Case 1:
Printf ("error 1/N ");
Break;
Case 2:
Printf ("Error 2/N ");
Break;
Case 3:
Printf ("error 3/N ");
Break;
Default:
Printf ("Unknown error ");
Break;
}
Exit (0 );
}

Return;
}

The preceding routine is very simple, and the exception handling mechanism is used in the program, which makes the program code very compact, clear, and easy to understand. When an exception occurs during the running of the program, the control flow performs a local jump (the Code module that enters the Exception Processing is inside the same function ), in this case, the GOTO statement can be used for implementation. However, the setjmp and longjmp methods are more rigorous and friendly. The execution flow of the program is 17-1.

 

Setjmp and longjmp are combined to achieve non-local jump of the program

Haha! This is what the GOTO statement cannot implement. That's why setjmp and longjmp are combined in C language. It provides a true exception handling mechanism. In fact, the routine in the previous article has demonstrated the non-local jump scenario of the longjmp function. To better demonstrate the differences between local jump and non-local jump, let's make a small change based on the previous routine. The Code is as follows:

Void func1 ()
{
// Execute other code
// Determine whether an error occurs in the program's remote connection. If an error exists, it will jump!
If (1) longjmp (mark, 1 );
}

Void func2 ()
{
// Execute other code
// Determine whether an error occurs in the program's remote connection. If an error exists, it will jump!
If (2) longjmp (mark, 2 );
}

Void func3 ()
{
// Execute other code
// Determine whether an error occurs in the program's remote connection. If an error exists, it will jump!
If (-1) longjmp (mark,-1 );
}

Void main (void)
{
Int jmpret;

Jmpret = setjmp (Mark );
If (jmpret = 0)
{
// Execute other code

// Exceptions may occur during the execution of the following functions.
Func1 ();

Func2 ();

Func3 ();

// Execute other code
}
Else
{
// Error Handling Module
Switch (jmpret)
{
Case 1:
Printf ("error 1/N ");
Break;
Case 2:
Printf ("Error 2/N ");
Break;
Case 3:
Printf ("error 3/N ");
Break;
Default:
Printf ("Unknown error ");
Break;
}
Exit (0 );
}

Return;
}

Looking back, is this similar to the exception handling model provided in C ++. Exception transmission can span one or more functions. This indeed provides a sound exception handling programming mechanism or means for C programmers.

Special notes when using setjmp and longjmp

1. When setjmp and longjmp are used in combination, they must have a strict sequential execution order, that is, the setjmp function is called first, and then the longjmp function is called, to restore to the previously saved "program execution point ". Otherwise, if you execute the longjmp function before setjmp is called, the execution flow of the program will be unpredictable, and it will easily cause the program to crash and exit. The sample code is as follows:

Class Test
{
Public:
Test () {printf ("constructor/N ");}
~ Test () {printf ("destructor/N ");}
} OBJ;

// Note that the global variable obj is declared above.

Void main (void)
{
Int jmpret;

// Note that the program will crash and exit unconditionally.
Func1 ();
While (1 );

Jmpret = setjmp (Mark );
If (jmpret = 0)
{
// Execute other code

// Exceptions may occur during the execution of the following functions.
Func1 ();

Func2 ();

Func3 ();

// Execute other code
}
Else
{
// Error Handling Module
Switch (jmpret)
{
Case 1:
Printf ("error 1/N ");
Break;
Case 2:
Printf ("Error 2/N ");
Break;
Case 3:
Printf ("error 3/N ");
Break;
Default:
Printf ("Unknown error ");
Break;
}
Exit (0 );
}

Return;
}

The preceding program running result is as follows:
Constructor
Press any key to continue

Indeed, the above program crashes because longjmp is called in the func1 () function, but the program has not yet called setjmp to save a program execution point. Therefore, the execution flow of the program is unpredictable. This results in very serious program consequences. For example, in the above program, an object is constructed, but when the program crashes and exits, its destructor are not called by the system to clear necessary resources. So such a program is very dangerous. (Note that the above program is a C ++ program, so when you demonstrate and test this routine, change the source file extension to XXX. cpp ).

2. In addition to calling the setjmp function, call the longjmp function (that is, longjmp must have the corresponding setjmp function. In addition, there is also a very important rule, that is, longjmp calls have certain Domain requirements. This is too abstract. Let's look at an example first, as shown below:

Int sub_func ()
{
Int jmpret, be_modify;

Be_modify = 0;

Jmpret = setjmp (Mark );
If (jmpret = 0)
{
// Execute other code
}
Else
{
// Error Handling Module
Switch (jmpret)
{
Case 1:
Printf ("error 1/N ");
Break;
Case 2:
Printf ("Error 2/N ");
Break;
Case 3:
Printf ("error 3/N ");
Break;
Default:
Printf ("Unknown error ");
Break;
}

// Pay attention to this statement. The program exits with conditions.
If (be_modify = 0) Exit (0 );
}

Return jmpret;
}

Void main (void)
{
Sub_func ();

// Note that although longjmp is called after setjmp, it is beyond the scope of setjmp.
Longjmp (mark, 1 );
}

If you run or debug the above Program (one-step tracking) and find it amazing, even when longjmp is executed, the program can return to the execution point of setjmp and exit normally. But does this mean there is no problem with the above routine? Let's make minor changes to this program, as shown below:

Int sub_func ()
{
// Note that a little change is made here
Int be_modify, jmpret;

Be_modify = 0;

Jmpret = setjmp (Mark );
If (jmpret = 0)
{
// Execute other code
}
Else
{
// Error Handling Module
Switch (jmpret)
{
Case 1:
Printf ("error 1/N ");
Break;
Case 2:
Printf ("Error 2/N ");
Break;
Case 3:
Printf ("error 3/N ");
Break;
Default:
Printf ("Unknown error ");
Break;
}

// Pay attention to this statement. The program exits with conditions.
If (be_modify = 0) Exit (0 );
}

Return jmpret;
}

Void main (void)
{
Sub_func ();

// Note that although longjmp is called after setjmp, it is beyond the scope of setjmp.
Longjmp (mark, 1 );
}

Run or debug the program above (one-step tracking) and find it crashes. Why? This is because "longjmp is called before the setjmp function is called, otherwise the result is unpredictable" (as mentioned in the previous article, msdn provides a special description ). Why is this unpredictable? In fact, the reason is also very simple, that is, when the setjmp function is called, it stores the program execution environment, only within the current function scope (or later). If the function is returned to the upper (or higher) function environment, the environment of the program stored by setjmp will also be invalid, because the data in the stack may overwrite at this time, of course, this will lead to unpredictable execution consequences.

3. Do not assume that variables of the Register Type will always remain unchanged. After longjmp is called, variables of the Register Type in the routine will not be restored in the control flow returned by setjmp. (This is also mentioned in the previous article ). Variables of the register type are directly stored in registers instead of in memory to improve program running efficiency. Register variables are generally temporary variables. In C, they are defined by register, or programs that directly embed assembly code. This type of variables is rarely used. Therefore, you do not need to consider this when using setjmp and longjmp.

4. Special descriptions are also made in msdn. "In the C ++ program, be careful with the use of setjmp and longjmp, because setjmp and longjmp do not support object-oriented semantics in C ++ very well. Therefore, in C ++ programs, the exception handling mechanism provided by C ++ will be more secure ." Although C ++ is very compatible with C, it is not 100% fully compatible. For example, here is a good example. In C ++ programs, it cannot coexist well with setjmp and longjmp. In the subsequent articles, we will conduct in-depth research on how C ++ is compatible with the exception handling mechanism in C language.

Summary

Currently, I am very impressed with setjmp and longjmp. Although it is not as easy as the exception handling model provided in C ++, it is so useful in C language, it is already very good. To take it up to the next level, make setjmp and longjmp closer to the Exception Handling Model (I .e. try () catch () syntax) provided in C ++ ).

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.