非本地跳转(C语言)
包含头文件:<setjmp.h>
函数:setjmp(), longjmp()
setjmp 和 longjmp提供了一种类似于goto语句的机制,但它并不局限于一个函数的作用域之内。这些函数常用于深层嵌套的函数调用链。如果在某个底层的函数中检测到
了一个错误,你可以立即返回顶层函数,不必向调用链的每个中间层函数返回一个错误标志。
函数原型
`int stjmp (jmp_buf state);`
`void longjmp (jmp_buf state, int value);`
使用
1. 首先声明一个 jmp_buf 变量,使用setjmp()函数对它进行初始化,第一次使用函数setjmp()的返回值为0;在调用setjmp()函数时所处的函数就是顶层函数。
(这时类似于使用goto语句所设置的标志)。
2. 在需要对错误进行处理时,在底层函数中使用longjmp()函数后,执行流恢复执行的地点跳转到第一次使用setjmp所处的位置(标志处)。
并且此时setjmp()函数所返回的值为longjmp()的第二个参数。
3. 我们可以对setjmp()所返回的数值进行判断处理,对不同的错误类型进行不同的处理。
代码示例
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <assert.h>
jmp_buf restart;
typedef struct {
int m_value;
}TRAN, * PTRAN;
PTRAN
GetTran();
void
ProcessTran(PTRAN);
void
FreeTran(PTRAN);
int main (int argc, char *argv[])
{
int values;
PTRAN ptran = GetTran();
/*
**确立一个我们希望在longjmp的调用之后执行流恢复执行的地点
*/
values = setjmp(restart);
/*
**从longjmp返回后判断下一步执行什么
*/
switch (values) {
default:
/*
**longjmp被调用 -- 致命错误
*/
printf("Fatal error. \n");
break;
case 1:
/*
**longjmp被调用 -- 小错误
*/
printf("This is a small issue. \n");
case 0:
/*
**最初从setjmp返回的地点:执行正常操作
*/
if (ptran != NULL)
ProcessTran(ptran);
}
printf("\nProgram Over!\n");
printf("The lastest number is : %d\n", ptran->m_value);
FreeTran(ptran);
system("pause");
return 0;
}
PTRAN
GetTran() {
PTRAN ptran = (PTRAN)malloc(sizeof(TRAN));
if (!ptran)
return NULL;
ptran->m_value = 0;
return ptran;
}
void
ProcessTran(PTRAN _ptran) {
assert(_ptran != NULL);
while (1) {
_ptran->m_value += 10;
if (_ptran->m_value == 450) {
// 小错误
longjmp(restart, 1);
}
else if (_ptran->m_value == 1000) {
// 致命错误
longjmp(restart, 2);
}
}
}
void
FreeTran(PTRAN _ptran) {
assert(_ptran != NULL);
free(_ptran);
_ptran = NULL;
}