非局部跳转语句---setjmp和longjmp函数。非局部指的是,这不是由普通C语言goto,语句在一个函数内实施的跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中。
#include <setjmp.h>
Int setjmp(jmp_buf env);
返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值
Void longjmp(jmp_buf env,int val);
在希望返回到的位置调用setjmp,此位置在main函数中,因为直接调用该函数,所以其返回值为0.setjmp参数evn的类型是一个特殊的类型jmp_buf,这一数据类型是某种形式的数组,其中存放在调用longjmp时能用来恢复栈状态的所有信息。因为需要在另一个函数中引用env变量,所以规范的处理方式是将env变量定义为全局变量。
当检查到一个错误时,则以两个参数调用longjmp函数,第一个就是在调用setjmp时所用的env,第二个参数是具有非0值的val,它将成为从setjmp处返回的值。使用第二个参数的原因是对于一个setjmp可以有多个longjmp。
下面我们可以看一个简单的例子:
|
这个函数的运行结果是:
|
在使用longjmp跳转到setjmp中时,程序主动的退出了!相当于抛出一个异常退出!其实这两个函数可以模拟C++中的异常函数:
使用setjmp和longjmp要注意以下几点:
1、setjmp与longjmp结合使用时,它们必须有严格的先后执行顺序,也即先调用setjmp函数,之后再调用longjmp函数,以恢复到先前被保存的“程序执行点”。否则,如果在setjmp调用之前,执行longjmp函数,将导致程序的执行流变的不可预测,很容易导致程序崩溃而退出
2、不要假设寄存器类型的变量将总会保持不变。在调用longjmp之后,通过setjmp所返回的控制流中,程序中寄存器类型的变量将不会被恢复。寄存器类型的变量,是指为了提高程序的运行效率,变量不被保存在内存中,而是直接被保存在寄存器中。寄存器类型的变量一般都是临时变量,在C语言中,通过register定义,或直接嵌入汇编代码的程序。这种类型的变量。
longjmp必须在setjmp调用之后,而且longjmp必须在setjmp的作用域之内。具体来说,在一个函数中使用setjmp来初始化一个全局标号,然后只要该函数未曾返回,那么在其它任何地方都可以通过longjmp调用来跳转到 setjmp的下一条语句执行。实际上setjmp函数将发生调用处的局部环境保存在了一个jmp_buf的结构当中,只要主调函数中对应的内存未曾释放 (函数返回时局部内存就失效了),那么在调用longjmp的时候就可以根据已保存的jmp_buf参数恢复到setjmp的地方执行。
实例:https://github.com/FredericGuo/CoffeeCatch.JNI
相关推荐
在C语言中,使用goto和标签的方式模拟try catch的功能,使用setjmp和longjmp方式模拟try catch的功能,两种方式都可以使用,setjmp的方式可以支持try catch嵌套,goto的方式不支持嵌套,但是jmpbuf的开销是比较大的...
2. **模拟try-catch** 要在C语言中模仿Java的try-catch模型,可以使用预处理器宏、函数指针和结构体等技术。通常的做法是定义一个异常结构体,包含错误码、错误信息等字段,以及一个处理函数指针。在"try"块中,...
7. **错误处理**:如何通过适当的错误处理机制来增强代码的健壮性,如使用assert、try-catch等。 8. **算法与数据结构**:软件可能包含排序算法(如冒泡、选择、插入、快速、归并等)、查找算法(如线性查找、二分...
C++提供了异常处理机制,可以使用`try-catch`语句块来捕获并处理这些异常,确保程序的稳定运行。 6. **数据持久化**: 除了文件操作外,还可以考虑使用序列化技术将对象转换为可存储的格式,如JSON或XML,然后写入...
C++的异常处理机制(try-catch-finally)是处理这类问题的有效方式。 9. **用户接口**:虽然这是一个控制台模式的应用,但仍需提供用户友好的交互界面。可以使用C++的iostream库来读取用户输入,并通过cout输出结果...
在MFC应用中,通常会在C++的try/catch基础上,使用BEGIN TRY/BEGIN CATCH宏进行异常处理,这样既可以处理C++标准异常,也可以处理MFC特定的异常。 结构化异常处理(Structured Exception Handling,SEH)是Windows...
而在C语言中,由于缺乏内置的支持,程序员需要通过其他方式来模拟这一功能。 一种常见的方法是使用longjmp和setjmp函数。这两个函数来自C标准库中的`<setjmp.h>`头文件,它们允许程序员创建一个“跳板”,当发生...
这段代码是用C语言模拟了一个简单的爱情故事,通过函数`love(boy, girl)`来描述一对恋人间的关系发展。在代码中,`boy`和`girl`被当作对象处理,有各自的属性和行为。让我们详细分析一下其中涉及的C语言知识点。 1....
在C异常处理机制中,通常会定义一系列宏来模仿`try-catch`块的行为。例如,`try`宏会创建一个异常帧(`Except_frame`结构体),并将其压入自定义的异常堆栈`Except_stack`中。这个异常帧包含了`setjmp`保存的环境...
- 错误处理:通过try-catch机制或条件判断语句处理可能出现的错误,如文件打开失败、输入格式错误等。 4. **功能实现** - 收支记录:为每笔交易创建结构体,包含事件描述、金额、日期等字段,然后在内存中创建一...
通过使用异常处理机制(try-catch块),你可以优雅地处理这些错误并给出用户友好的反馈。 7. **设计模式**:在构建这样的系统时,可以应用一些设计模式,如工厂模式(用于创建不同类型的文件和目录对象)、单例模式...
6. **异常处理**:了解如何在代码中插入try、catch块来捕获和处理运行时错误。 7. **MFC(Microsoft Foundation Classes)框架**:学习如何利用MFC进行Windows GUI程序的开发,包括窗口、控件、消息处理等。 8. **...
异常处理是Java中的重要特性,通过try-catch-finally结构来捕获和处理运行时错误。集合框架包括ArrayList、LinkedList、HashSet、HashMap等,是存储和管理数据的关键工具。多线程使得程序可以同时执行多个任务,考生...
7. **异常处理**:在模拟程序中,可能会使用try-catch块来捕获和处理可能出现的错误,如无效的航班号、座位已被预订等情况。 8. **函数重载**:根据不同的输入参数,同一函数名可以有多个不同的实现,这是C++的多态...
虽然C++没有直接的`finally`块,但可以使用`try-finally`的模拟实现。 6. **自定义异常**:除了使用标准库中的异常类,程序员还可以创建自己的异常类,这有助于提供更具体的错误信息和处理策略。 7. **异常安全性*...
在`try`块后面,`catch`块可以放在`finally`块之前或之后,但不能在`try`块内部,所以A、C和D都是错误的,B(最后)是正确的。 4. `try`语句后的必备结构: `try`语句后面通常需要一个`catch`块来捕获异常,但...
解析:(P253)C++的异常处理机制由try、catch和throw关键字构成。try块包含可能抛出异常的代码,catch块用于捕获和处理异常,而throw用于抛出异常。 13. C++中,如何声明一个指向整型数组的指针? A. int *p; B. int...
在嵌入式Linux环境中,C语言本身并不支持异常处理,但可以通过使用C++或者编写特定的错误处理机制来模拟异常处理。对于C++,其异常处理机制完全兼容于标准C++,因此可以在嵌入式Linux系统上使用。对于纯C环境,通常...
不过,现代C库(如glibc)有时会使用setjmp/longjmp函数来模拟异常处理。 至于C#,它的异常处理机制与Java非常相似,也是基于try-catch-finally结构。C#还引入了using关键字,用于自动管理实现了IDisposable接口的...