实现上下文保存和恢复的一种方式--setjmp与longjmp

简介: 实现上下文保存和恢复的一种方式--setjmp与longjmp

函数原型:

int setjmp(jmp_buf envbuf);

setjmp函数用缓冲区envbuf保存系统堆栈的内容,以便后续的longjmp函数使用。setjmp函数初次启用时返回0值。

void longjmp(jmp_buf envbuf, int val);

longjmp函数中的参数envbuf是由setjmp函数所保存的堆栈环境,参数val设置setjmp函数的返回值。longjmp函数本身是没有返回值的,它执行后跳转到保存envbuf参数的setjmp函数调用,并由setjmp函数调用返回,此时setjmp函数的返回值就是val。

上面的说明有点拗口,通俗的解释是:先调用setjmp,用变量envbuf记录当前的位置,然后调用longjmp,返回envbuf所记录的位置,并使setjmp的返回值为val。当时用longjmp时,envbuf的内容被销毁了。其实这里的“位置”一词真正的含义是栈定指针。

接着让我们看一个小例子吧:

#include <stdio.h> 
#include <setjmp.h>
jmp_buf buf;
void test() {
  printf("in test() \n");
  longjmp(buf, 1);
  printf("333333\n");
}
int main()
{
  if (setjmp(buf))
    printf("111111\n");
  else {
    printf("222222\n");
    test();
  }
  getchar();
  return 0;
}

断点调试,第一次buf为空,还没有保存上下文。

第二次buf已经存在值了。

执行结果

分析:程序先走到setjmp。由于setjmp第一次执行返回的结果是0,所以走的else分支,打印"22222"。接着跳转到test()函数中,继续执行printf打印"in test()“。然后走到longjmp这里,由于longjmp的功能,接下来会跳转到main的setjmp这里继续执行。此时setjmp是第二次执行了,返回值为非0,所以会进入if分支,打印出"111111”。


推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,点击立即学习:

相关文章
|
2月前
|
存储 C语言 图形学
C 函数中如何保存 Lua 的数据(1)
C 函数中如何保存 Lua 的数据(1)
38 0
|
安全
VS2019 error C4703: 使用了可能未初始化的本地指针变量 错误
VS2019 error C4703: 使用了可能未初始化的本地指针变量 错误
655 0
VS2019 error C4703: 使用了可能未初始化的本地指针变量 错误
|
2月前
|
C语言 C++ 索引
C 函数中如何保存 Lua 的数据(2)
C 函数中如何保存 Lua 的数据(2)
24 1
保存变量并且在程序结束时候还原的方法
基本思路:在操作前构造一个类保存当前变量状态,在类析构中还原数值。
|
4月前
|
C语言
C语言函数传递了指针,值没有被修改的原因及解决方法
C语言函数中传递了指针作为参数,确切来说是传递了指向变量的内存地址作为参数,可经过函数内的修改之后,该指针指向的变量的值为什么不会被修改?就像下方这个函数:
65 1
|
10月前
|
C语言 C++
【C++】 --- 写个函数在main函数执行前先运行
【C++】 --- 写个函数在main函数执行前先运行
83 0
|
关系型数据库 MySQL Go
[Golang]存在调用同一个包内某个结构体的方法出错?可能是未初始化结构体
[Golang]存在调用同一个包内某个结构体的方法出错?可能是未初始化结构体
定义函数,并用指针交换两个变量内容(正确版和错误版+错误原因)
定义函数,并用指针交换两个变量内容(正确版和错误版+错误原因)
65 0
定义函数,并用指针交换两个变量内容(正确版和错误版+错误原因)
【C#】【ffmpeg】外部调用线程执行ffmepg读取返回的信息乱码问题
【C#】【ffmpeg】外部调用线程执行ffmepg读取返回的信息乱码问题
144 0
【C#】【ffmpeg】外部调用线程执行ffmepg读取返回的信息乱码问题
|
SQL 数据库连接 数据库
实时错误“91” 对象变量或with块变量未设置”
实时错误“91” 对象变量或with块变量未设置”
562 0
实时错误“91” 对象变量或with块变量未设置”