异常处理,保证代码稳定的必经之步----小话c语言(12)
来源:互联网 发布:大数据全洞察 编辑:程序博客网 时间:2024/05/16 10:31
[Mac 10.7.1 Lion Intel-based x64 gcc4.2.1]
Q: c语言的异常处理可以使用什么?
A: 可以使用setjmp和longjmp的组合。一个是保存处理异常前执行的环境,一个是调回原来执行的环境。
int setjmp(jmp_buf env);参数env的类型jmp_buf定义如下:
/* * _JBLEN is number of ints required to save the following: * eax, ebx, ecx, edx, edi, esi, ebp, esp, ss, eflags, eip, * cs, de, es, fs, gs == 16 ints * onstack, mask = 2 ints */#define _JBLEN (18)typedef int jmp_buf[_JBLEN];
可以看到jmp_buf是个数组类型,含有18个int类型数据,包括eax, ebp, esp, eip等环境变量。
它会返回0,便于外部判断进入异常处理逻辑。
void longjmp(jmp_buf env, int val);第一个参数为setjmp设置的jmp_buf, 第二个参数为返回异常处理的异常参数,可自定义。
下面是个简单的例子:
#include <stdio.h>#include <string.h>#include <setjmp.h>#define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue));#define PRINT_STR(str) printf(#str" is %s\n", (str));jmp_buf buf;// exception processvoid exception_process(){ printf("exception process begin...\n"); longjmp(buf, 1); // return to the normal process printf("never execute this...\n"); // so, this line can't be executed}int main(){ int ret; printf("main begin...\n"); ret = setjmp(buf); // save current execute enviroment, go to exception process if(ret) { // returned by exception process printf("pass exception process ...\n"); printf("main end ...\n"); } else { exception_process(); } return 0;}可以看到setjmp和longjmp因为共同操作了jmp_buf buf;全局变量,所以它们可以在不同函数跳转并正确返回执行。main函数开始setjmp(buf)一定会返回0, 所以进入exception_process例程,进入后,longjmp(buf, 1);会返回之前执行的地方,进入main的if(ret)逻辑中,执行异常发生后的代码。
执行结果:
Q: 上面代码中的buf全局变量可以采用局部变量吗?
A: 是的,但是需要将buf传递给异常处理部分。如下代码:
#include <stdio.h>#include <string.h>#include <setjmp.h>#define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue));#define PRINT_STR(str) printf(#str" is %s\n", (str));// exception processvoid exception_process(jmp_buf buf){ printf("exception process begin...\n"); longjmp(buf, 1); // return to the normal process printf("never execute this...\n"); // so, this line can't be executed}int main(){ jmp_buf buf; int ret; printf("main begin...\n"); ret = setjmp(buf); // save current execute enviroment, go to exception process if(ret) { // returned by exception process printf("pass exception process ...\n"); printf("main end ...\n"); } else { exception_process(buf); } return 0;}可以看到exception_process多了一个参数,用于buf的传递。
运行结果:
Q: 如果异常原因有几种,怎么分辨处理?
A: 这个就需要用到longjmp第二个参数了。
#include <stdio.h>#include <string.h>#include <setjmp.h>#define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue));#define PRINT_STR(str) printf(#str" is %s\n", (str));// input error processvoid exception_input_error_process(jmp_buf buf){ printf("exception input error process begin...\n"); longjmp(buf, 1001); // return to the normal process, 1001 means exception error number}// input too big processvoid exception_input_too_big_process(jmp_buf buf){ printf("exception input too big process begin...\n"); longjmp(buf, 1002); // return to the normal process, 1002 means exception error number}int main(){ jmp_buf buf; int ret, scanf_ret; int n; printf("main begin...\n"); // input n printf("input n:"); scanf_ret = scanf("%d", &n); ret = setjmp(buf); // save current execute enviroment, go to exception process if(ret) { // returned by exception process printf("pass exception process ...\n"); if(ret == 1001) { printf("exception 1001 process end...\n"); } else if(ret == 1002) { printf("exception 1002 process end...\n"); } printf("main end ...\n"); } else { if(scanf_ret < 1) exception_input_error_process(buf); else if(n > 100) exception_input_too_big_process(buf); } return 0;}如上,如果输入整形格式不正确,那么进入输入错误处理;如果输入的整形超过100,那么进入输入过大的处理。
运行结果:
输入错误数据a:
输入数据为101:
输入数据50:
此时没有发生异常。
xichen
2012-5-18 15:18:16
- 异常处理,保证代码稳定的必经之步----小话c语言(12)
- C语言的那些小秘密之异常处理
- C语言的那些小秘密之【异常处理】
- C语言的那些小秘密之异常处理
- C语言的异常处理
- C语言的异常处理
- C语言的异常处理
- 异常处理(二、C语言的异常处理)
- C语言异常处理
- C语言异常处理
- 异常处理---C语言
- C语言的那些小秘密——异常处理(转bigloomy)
- 神奇的C语言五:异常处理
- C语言编程准则之稳定篇
- C语言下的setjmp longjmp(C 语言异常处理)
- 嵌入式C小秘密之你不知道的异常处理
- c语言异常处理之longjmp 和 setjmp
- C语言实现异常处理
- dwr的应用
- Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面
- 智能指针
- VS2008制作ActiveX,并打包为CAB(2)
- Android 的Margin和Padding属性以及支持的长度单位
- 异常处理,保证代码稳定的必经之步----小话c语言(12)
- java 泛型使用和不定参数函数定义
- Android Handler Message多线程实例
- C# WinForm 父窗体 子窗体 传值
- 【C趣味100题】【Code_00】【开篇言】
- 从生活角度学习c++
- 收藏 不显示删除回复显示所有回复显示星级回复显示得分回复 dev 控件中 gridControl1 控件的button列 事件中如何获取所在行的某列的值
- FreeBSD 10 将使用 Clang 编译器替换 GCC
- 隐藏控件