【C语言基础】C语言异常捕获机制 - setjmp

C语言异常捕获机制 - setjmp

快速入门

想快速入门该模块请访问:介绍数据接口示例代码

介绍

C语言没有C++或Java的异常捕获机制,但可以通过setjmp/longjmp实现类似的效果:

  • 使用setjmp保存当前执行环境到jmp_buf,然后默认返回0。
  • 程序继续执行,到某个地方调用longjmp,传入上面保存的jmp_buf,以及另一个整形值(我们称他为异常码)。
  • 此时执行点又回到调用setjmp的返回处,且返回值变成longjmp设置的值
  • 可以实现跨函数跳转

注意:

  • 使用gcc或者clang优化编译的时候,可能导致结果不符合预期。可以参考某大神的示例代码。因此不推荐时候,异常捕获最好还是直接使用返回值形式进行调用。https://gist.github.com/nnkken/8aea1eaf1e43a963a9309c98ae4f891e

  • 此外,setjmp只能设置最近一次执行环境,而且longjmp也只能是回到上一次设置setjmp中,因此并不支持设置多个执行环境

数据与接口

头文件

  • #include <setjmp.h>

数据

  • ​环境堆栈类型 : jmp_buf

接口

  • ​设置环境堆栈 int setjmp( jmp_buf env );

  • ​跳转至环境堆栈并返回指定值 void longjmp( jmp_buf env, int value );

接口介绍

setjmp

​ setjmp函数用于保存程序的运行时的堆栈环境,接下来的其它地方,你可以通过调用longjmp函数来恢复先前被保存的程序堆栈环境。当 setjmp和longjmp组合一起使用时,它们能提供一种在程序中实现“非本地局部跳转”(“non-local goto”)的机制。并且这种机制常常被用于来实现,把程序的控制流传递到错误处理模块之中;或者程序中不采用正常的返回(return)语句,或函数的正常调用等方法,而使程序能被恢复到先前的一个调用例程(也即函数)中。

对setjmp函数的调用时,会保存程序当前的堆栈环境到env参数中;接下来调用longjmp时,会根据这个曾经保存的变量来恢复先前的环境,并且当前的程序控制流,会因此而返回到先前调用setjmp时的程序执行点。此时,在接下来的控制流的例程中,所能访问的所有的变量(除寄存器类型的变量以外),包含了longjmp函数调用时,所拥有的变量。

longjmp

​ longjmp函数用于恢复先前程序中调用的setjmp函数时所保存的堆栈环境。setjmp和longjmp组合一起使用时,它们能提供一种在程序中实现“非本地局部跳转”(“non-local goto”)的机制。并且这种机制常常被用于来实现,把程序的控制流传递到错误处理模块,或者不采用正常的返回(return)语句,或函数的正常调用等方法,使程序能被恢复到先前的一个调用例程(也即函数)中。

对setjmp函数的调用时,会保存程序当前的堆栈环境到env参数中;接下来调用longjmp时,会根据这个曾经保存的变量来恢复先前的环境,并且因此当前的程序控制流,会返回到先前调用setjmp时的执行点。此时,value参数值会被setjmp函数所返回,程序继续得以执行。并且,在接下来的控制流的例程中,它所能够访问到的所有的变量(除寄存器类型的变量以外),包含了longjmp函数调用时,所拥有的变量;而寄存器类型的变量将不可预料。setjmp函数返回的值必须是非零值,如果longjmp传送的value参数值为0,那么实际上被setjmp返回的值是1。

伪代码

res = setjmp(env);
if (res == 0) {try dosomething...(contain longjmp)
} else {exception dosomething...
}

示例:比大小

#include <stdio.h>
#include <setjmp.h>#define CORRECT_NUM 5
jmp_buf g_env;void err_1(void)
{printf("raise err 1: num is small\n");longjmp(g_env, 1);
}void err_2(void)
{printf("raise err 2: num is large\n");longjmp(g_env, 2);
}void work_func(int num)
{if (num == CORRECT_NUM) {printf("num is correct\n");} else if (num < CORRECT_NUM) {err_1();} else {err_2();}
}int main() {int num;scanf("%d", &num);int res = setjmp(g_env);if (res == 0) {/* try */work_func(num);} else {/* exception */printf("res = %d\n", res);}return 0;
}

参考链接

  1. https://zhuanlan.zhihu.com/p/82492121
  2. http://www.360doc.com/content/22/0119/23/78473664_1014100527.shtml
  3. https://www.runoob.com/cprogramming/c-standard-library-setjmp-h.html
  4. https://gist.github.com/nnkken/8aea1eaf1e43a963a9309c98ae4f891e

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/526570.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语言基础】C语言异常捕获机制 - assert

C语言异常捕获机制 - assert 快速入门 想快速入门该模块请访问&#xff1a;介绍&#xff0c;数据接口&#xff0c;示例代码 介绍 通常一个良好的代码功能运行环境都有功能运行前检查和运行后检查两个方面。&#xff23;语言中提供了assert机制来做这件事情 assert 的作用是…

【c语言数据结构】二叉树

c语言数据结构完全二叉树 快速开始 直接参考示例代码即可 介绍 概念 二叉树&#xff08;Binary tree&#xff09;是树形结构的一个重要类型。 许多实际问题抽象出来的数据结构往往是二叉树形式&#xff0c;即使是一般的树也能简单地转换为二叉树&#xff0c; 二叉树的存…

git 指令全集

git 指令全集 指令集参考这里&#xff0c;后续会继续整理 https://www.runoob.com/git/git-tutorial.html 基本使用流程 场景&#xff11;&#xff1a;建立新仓 首先在本地新建一个仓 ~$ mkdir git_workspace ~$ git init与远程仓建立连接 # 查看所有的远端分支 -$ git rem…

UTHash使用教程

UTHash使用教程 快速入门 想快速入门该模块请访问&#xff1a;介绍&#xff0c;数据接口&#xff0c;示例代码 介绍 Hash &#xff1a;散列&#xff0c;通过关于键值(key)的函数&#xff0c;将数据映射到内存存储中一个位置来访问。这个过程叫做Hash&#xff0c;这个映射函…

【C语言基础】gdb调试工具的使用

gdb调试教程 快速入门 要想快速入门gdb调试&#xff0c;可以直接翻阅基本案例&#xff1a;采内存 介绍 GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。 对于一名Linux下工作的c/c程序员&#xff0c;gdb是必不可少的工具 …

C/C++队列与循环队列

C/C数据结构 - 队列 循环队列 快速入门 介绍 1. 队列的定义 队列是一种线性存储结构&#xff0c;每次对队列的增删操作如下 增&#xff1a;在队列尾部添加元素 删&#xff08;取出&#xff09;&#xff1a;在队列头部删除元素 这种数据存储方式遵循“先进先出”&#xff0…

PyQt特殊对话框介绍

PyQt特殊对话框 对话框基类&#xff1a;QDialog 对话框基本用法&#xff1a; 模态窗口&#xff1a; 当窗口设置为模态窗口时&#xff0c;不能对其父级别的窗口进行操作。QTdesigner里有控件可以勾选Func: QtWidgets.Dialog.setModal(True) [ True | False ] 窗口执行 exec&am…

PyQt5 让窗口在桌面居中的办法

屏幕居中核心函数 在我们开发的UI类中定义一个center方法&#xff0c;&#xff08;方法名自定&#xff0c;内容如下&#xff09;。其中QDesktopWideget方法在Qtwidgets头文件中。 然后在 __init__()中调用该 self.center()方法即可。 # 屏幕居中def center(self):# 获取窗口大…

PyQt5 QLineEdit输入密码

单行编辑器 QLineEdit 输入密码 单行编辑器直接继承于QWidget 常用方法&#xff1a; 设置显示模式&#xff1a;在设置密码栏常会使用这种模式 方法QLineEdit.setEchoMode 用法 假设你有一个QLineEdit()组件 self.UserpswdEdit QLineEdit()则你可以使用下面三种方式定义输…

Arduino 软件开发(一): GPIO读写

Arduino 软件开发&#xff08;一&#xff09; 目录 核心运行函数&#xff0c; 基础语法&#xff0c;数字控制&#xff0c;模拟控制 核心运行函数 void setup() 当Arduino程序开始运行时会调用setup()函数。通常setup()函数完成初始化一些变量、配置引脚状态及初始化调用的库…

JavaScript学习笔记:类与导包实例

NodeJS类与导包 在工程上&#xff0c;一个文件就是一个独立的模块&#xff0c;仅包含一个类。我们可以称之为类文件。因此当我们要使用这个模块的时候&#xff0c;我们会将这个类文件作为一个包导入到调用的文件里。方法如下&#xff1a; 0. 目录结构如下 - src|__ main.js|…

JavaScript学习笔记:常量,枚举,宏定义

NodeJS常量&#xff08;fake&#xff1a;宏定义&#xff09; 因为之前C/C代码开发习惯了&#xff0c;会用到一些宏定义来替换一些表意不明的数字&#xff08;就是含义不清的数字&#xff09;。而JS没有这种宏定义。上网找到一个链接作为参考&#xff1a;https://www.itranslat…

JavaScript学习笔记:函数与箭头函数

NodeJS函数 由于js是弱语言&#xff0c;因此&#xff0c;函数的入参和出参可以为任意形式而不用指定类型。当然也没有办法使用冒号的形式进行参数类型注释。但是typescript可以使用冒号形式进行参数类型注释。 1. 普通的函数定义 不带参数形式printHello带参数形式plus使用re…

Python学习笔记(1):用户输入,终端输入

#用户输入&#xff0c;操作 print("python 用户输入操作")# input(提示字符串)&#xff0c;函数阻塞程序&#xff0c;并提醒用户输入字符串 instr input("please input the string: ") print("input >> " instr)# 将输入的字符串转化成整…

Python学习笔记(2):生成器

介绍 我们可以通过列表生成式简单直接地创建一个列表&#xff0c;但是受到内存限制&#xff0c;列表容量肯定是有限的。而且&#xff0c;创建一个包含100万个元素的列表&#xff0c;不仅占用很大的存储空间&#xff0c;而且如果我们仅仅需要访问前面几个元素&#xff0c;那后面…

Python学习笔记(3):zipfile解压库

简介 python自带zipfile解压库&#xff0c;导入方式如下 import zipfile批量解压 先尝试无密码解压&#xff0c;如果失败&#xff0c;就输入密码。但是zipfile解压大文件速度很慢。 path rL:/resource/zipPackage passwd b123456 def compressFromZip():for temp_name in…

数字万用表使用方法

数字万用表使用方法 简介&#xff1a;数字万用表相对来说&#xff0c;属于比较简单的测量仪器。本篇&#xff0c;作者就教大家数字万用表的正确使用方法。从数字万用表的电压、电阻、电流、二极管、三极管、MOS场效应管的测量等测量方法开始&#xff0c;让你更好的掌握万用表测…

Python学习笔记(4):Python如何设置类似C语言静态函数

介绍 模块封装时候&#xff0c;希望有一些函数不被外部直接调用。C语言通常采用static int function()形式以及头文件形式作为标识。而python不存在头文件&#xff0c;但可以通过修饰符staticmethod进行代替。 staticmethod def your_function():# 你的代码print("your …

c++ 字符串相等比较

介绍 在C 中比较字符串的技术 (Techniques to Compare Strings in C) Strings in C can be compared using either of the following techniques: 可以使用以下两种技术之一来比较C 中的字符串&#xff1a; String strcmp() function 字符串strcmp&#xff08;&#xff09;函…

ffmpeg下载安装 多段ts视频m3u8下载

如何下载多段ts视频 m3u8 ffmpeg ffmpeg使用教程 下载 Windows下载方法 step1. 官网下载地址 点此进入下载地址 step2. 选择 Windows EXE files 中的Windows builds by BtbN 这会跳转到github页面中。 step3. 选择对应的linux平台或者windows平台进行下载 安装 step1.…