- 浏览: 2036431 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (651)
- ACE (35)
- BAT (9)
- C/C++ (116)
- fast-cgi (14)
- COM (27)
- python (59)
- CGI (4)
- C# (2)
- VC (84)
- DataBase (29)
- Linux (96)
- P2P (6)
- PHP (15)
- Web (6)
- Memcached (7)
- IME输入法 (11)
- 设计模式 (2)
- 搜索引擎 (1)
- 个人情感 (4)
- 笔试/面试 (3)
- 一亩三分地 (33)
- 历史 (2)
- 地理 (1)
- 人物 (3)
- 经济 (0)
- 不仅仅是笑哦 (43)
- 小故事大道理 (2)
- http://www.bjdsmyysjk120.com/ (0)
- http://www.bjdsmyy120.com/ (0)
- 它山之石可以攻玉 (15)
- 大学生你关注些什么 (28)
- 数据恢复 (1)
最新评论
-
luokaichuang:
这个规范里还是没有让我明白当浏览器上传文件时,STDIN的消息 ...
FastCGI规范 -
effort_fan:
好文章!学习了,谢谢分享!
com技术简介 -
vcell:
有错误os.walk(strPath)返回的已经是全部的文件和 ...
通过python获取目录的大小 -
feifeigd:
feifeigd 写道注意:文章中的CPP示例第二行 #inc ...
ATL入门:利用ATL编写简单的COM组件 -
feifeigd:
注意:文章中的CPP示例第二行 #include " ...
ATL入门:利用ATL编写简单的COM组件
将对setjmp与longjmp的具体使用方法和适用的场合,进行一个非常全面的阐述。
另外请特别注意,setjmp函数与longjmp函数总是组合起来使用,它们是紧密相关的一对操作,只有将它们结合起来使用,才能达到程序控制流有效转移的目的,才能按照程序员的预先设计的意图,去实现对程序中可能出现的异常进行集中处理。 void main( void ) jmpret = setjmp( mark ); // 其它代码的执行 // 其它代码的执行 // 其它代码的执行 return; 上面的例程非常地简单,其中程序中使用到了异常处理的机制,这使得程序的代码非常紧凑、清晰,易于理解。在程序运行过程中,当异常情况出现后,控制流是 进行了一个本地跳转(进入到异常处理的代码模块,是在同一个函数的内部),这种情况其实也可以用goto语句来予以很好的实现,但是,显然setjmp与 longjmp的方式,更为严谨一些,也更为友善。程序的执行流如图17-1所示。
void Func1() void Func2() void Func3() void main( void ) jmpret = setjmp( mark ); // 下面的这些函数执行过程中,有可能出现异常 Func2(); Func3(); // 其它代码的执行 return; class Test //注意,上面声明了一个全局变量obj void main( void ) // 注意,这里将会导致程序崩溃,无条件退出 jmpret = setjmp( mark ); // 下面的这些函数执行过程中,有可能出现异常 Func2(); Func3(); // 其它代码的执行 return; 上面的程序运行结果,如下: 的确,上面程序崩溃了,由于在Func1()函数内,调用了longjmp,但此时程序还没有调用setjmp来保存一个程序执行点。因此,程序的执行 流变的不可预测。这样导致的程序后果是非常严重的,例如说,上面的程序中,有一个对象被构造了,但程序崩溃退出时,它的析构函数并没有被系统来调用,得以 清除一些必要的资源。所以这样的程序是非常危险的。(另外请注意,上面的程序是一个C++程序,所以大家演示并测试这个例程时,把源文件的扩展名改为 xxx.cpp)。 2、除了要求先调用setjmp函数,之后再调用longjmp函数(也即longjmp必须有对应的setjmp函数)之外。另外,还有一个很重要的规则,那就是longjmp的调用是有一定域范围要求的。这未免太抽象了,还是先看一个示例,如下: int Sub_Func() jmpret = setjmp( mark ); //注意这一语句,程序有条件地退出 return jmpret; void main( void ) // 注意,虽然longjmp的调用是在setjmp之后,但是它超出了setjmp的作用范围。 如果你运行或调试(单步跟踪)一下上面程序,发现它真是挺神奇的,居然longjmp执行时,程序还能够返回到setjmp的执行点,程序正常退出。但是这就说明了上面的这个例程的没有问题吗?我们对这个程序小改一下,如下: int Sub_Func() jmpret = setjmp( mark ); //注意这一语句,程序有条件地退出 return jmpret; void main( void ) // 注意,虽然longjmp的调用是在setjmp之后,但是它超出了setjmp的作用范围。 运行或调试(单步跟踪)上面的程序,发现它崩溃了,为什么?这就是因为,“在调用setjmp的函数返回之前,调用longjmp,否则结果不可预料” (这在上一篇文章中已经提到过,MSDN中做了特别的说明)。为什么这样做会导致不可预料?其实仔细想想,原因也很简单,那就是因为,当setjmp函数 调用时,它保存的程序执行点环境,只应该在当前的函数作用域以内(或以后)才会有效。如果函数返回到了上层(或更上层)的函数环境中,那么setjmp保 存的程序的环境也将会无效,因为堆栈中的数据此时将可能发生覆盖,所以当然会导致不可预料的执行后果。 3、不要假象寄存器类型的变量将总会保持不变。在调用longjmp之后,通过setjmp所返回的控制流中,例程中寄存器类型的变量将不会被恢复。 (MSDN中做了特别的说明,上一篇文章中,这也已经提到过)。寄存器类型的变量,是指为了提高程序的运行效率,变量不被保存在内存中,而是直接被保存在 寄存器中。寄存器类型的变量一般都是临时变量,在C语言中,通过register定义,或直接嵌入汇编代码的程序。这种类型的变量一般很少采用,所以在使 用setjmp和longjmp时,基本上不用考虑到这一点。
与goto语句的作用类似,它能实现本地的跳转
这种情况容易理解,不过还是列举出一个示例程序吧!如下:
{
int jmpret;
if( jmpret == 0 )
{
// 其它代码的执行
// 判断程序远行中,是否出现错误,如果有错误,则跳转!
if(1) longjmp(mark, 1);
// 判断程序远行中,是否出现错误,如果有错误,则跳转!
if(2) longjmp(mark, 2);
// 判断程序远行中,是否出现错误,如果有错误,则跳转!
if(-1) longjmp(mark, -1);
}
else
{
// 错误处理模块
switch (jmpret)
{
case 1:
printf( "Error 1\n");
break;
case 2:
printf( "Error 2\n");
break;
case 3:
printf( "Error 3\n");
break;
default :
printf( "Unknown Error");
break;
}
exit(0);
}
}
setjmp与longjmp相结合,实现程序的非本地的跳转
呵呵!这就是goto语句所不能实现的。也正因为如此,所以才说在C语言中,setjmp与longjmp相结合的方式,它提供了真正意义上的异常处 理机制。其实上一篇文章中的那个例程,已经演示了longjmp函数的非本地跳转的场景。这里为了更清晰演示本地跳转与非本地跳转,这两者之间的区别,我 们在上面刚才的那个例程基础上,进行很小的一点改动,代码如下:
{
// 其它代码的执行
// 判断程序远行中,是否出现错误,如果有错误,则跳转!
if(1) longjmp(mark, 1);
}
{
// 其它代码的执行
// 判断程序远行中,是否出现错误,如果有错误,则跳转!
if(2) longjmp(mark, 2);
}
{
// 其它代码的执行
// 判断程序远行中,是否出现错误,如果有错误,则跳转!
if(-1) longjmp(mark, -1);
}
{
int jmpret;
if( jmpret == 0 )
{
// 其它代码的执行
Func1();
}
else
{
// 错误处理模块
switch (jmpret)
{
case 1:
printf( "Error 1\n");
break;
case 2:
printf( "Error 2\n");
break;
case 3:
printf( "Error 3\n");
break;
default :
printf( "Unknown Error");
break;
}
exit(0);
}
}
回顾一下,这与C++中提供的异常处理模型是不是很相近。异常的传递是可以跨越一个或多个函数。这的确为C程序员提供了一种较完善的异常处理编程的机制或手段。
setjmp和longjmp使用时,需要特别注意的事情
1、setjmp与longjmp结合使用时,它们必须有严格的先后执行顺序,也即先调用setjmp函数,之后再调用longjmp函数,以恢复到 先前被保存的“程序执行点”。否则,如果在setjmp调用之前,执行longjmp函数,将导致程序的执行流变的不可预测,很容易导致程序崩溃而退出。 请看示例程序,代码如下:
{
public:
Test()
~Test()
}obj;
{
int jmpret;
Func1();
while(1);
if( jmpret == 0 )
{
// 其它代码的执行
Func1();
}
else
{
// 错误处理模块
switch (jmpret)
{
case 1:
printf( "Error 1\n");
break;
case 2:
printf( "Error 2\n");
break;
case 3:
printf( "Error 3\n");
break;
default :
printf( "Unknown Error");
break;
}
exit(0);
}
}
构造对象
Press any key to continue
{
int jmpret, be_modify;
be_modify = 0;
if( jmpret == 0 )
{
// 其它代码的执行
}
else
{
// 错误处理模块
switch (jmpret)
{
case 1:
printf( "Error 1\n");
break;
case 2:
printf( "Error 2\n");
break;
case 3:
printf( "Error 3\n");
break;
default :
printf( "Unknown Error");
break;
}
if (be_modify==0) exit(0);
}
}
{
Sub_Func();
longjmp(mark, 1);
}
{
// 注意,这里改动了一点
int be_modify, jmpret;
be_modify = 0;
if( jmpret == 0 )
{
// 其它代码的执行
}
else
{
// 错误处理模块
switch (jmpret)
{
case 1:
printf( "Error 1\n");
break;
case 2:
printf( "Error 2\n");
break;
case 3:
printf( "Error 3\n");
break;
default :
printf( "Unknown Error");
break;
}
if (be_modify==0) exit(0);
}
}
{
Sub_Func();
longjmp(mark, 1);
}
发表评论
-
Berkeley DB 使用经验总结
2012-08-27 14:41 3086作者:陈磊 NoSQL是现在互联网Web2.0时代备受 ... -
嵌入式数据库系统Berkeley DB
2012-08-27 14:37 1533前言 UNIX/LINUX平台下的数据库种类非常多 ... -
C语言中标准输入流、标准输出流、标准错误输出流
2011-06-13 14:32 9293C语言中标准输入流、标准输出流、标准错误输出流 在 ... -
Rsync 实现原理
2011-05-12 20:06 8319Rsync 实现原理 前言 关于rsync的原始文档 ... -
c++简单的虚函数测试
2011-04-27 14:25 1020#include <iostream> u ... -
C++文件行查找
2011-04-26 14:10 1408#include <iostream> # ... -
c++偏特化简单示例
2011-04-13 11:17 2156c++偏特化 // temp1.c ... -
GDB调试精粹及使用实例
2011-03-16 14:06 1141GDB调试精粹及使用实例 一:列文件清单 1. ... -
简单的ini文件解析
2011-02-12 16:36 1623int GetKeyVal(const string s ... -
scanf族函数高级用法
2011-01-25 16:00 2562如何解释 fscanf(fd,&quo ... -
使用scons替代makefile(1)
2011-01-25 11:58 3733早在多年前我刚开始接触linux下的C程序时,经常被makef ... -
使用scons替代makefile(2)
2011-01-25 11:57 3584本篇文章接着上一篇进一步介绍scons的使用方法,主要介绍静态 ... -
使用scons替代makefile(3)
2011-01-25 11:55 4821在上两篇文章中已经简单介绍了用scons编译库文件,可执行程序 ... -
C 支持动态添加测试数据的测试代码
2011-01-13 17:22 1120/下面的定义为了支持可扩增。 //当需要增加一个新的测试用列 ... -
Linux下Makefile的automake生成
2010-12-28 16:55 1102******************helloworld.c* ... -
SCons笔记(详细版)
2010-12-23 16:11 105411. 基本使用 SConstruct文件就功能而言相当于Ma ... -
scons 学习
2010-12-23 11:14 2181scons 学习 作者:Sam(甄峰) sam_code@h ... -
scons随笔
2010-12-22 20:20 4707scons随笔 Scons是新一代的软件构件工具,或者说ma ... -
Scons在linux下的安装和使用
2010-12-21 11:59 3286因为正在用的一个开源软件需要的Developm ... -
排列组合的实现
2010-12-20 12:41 1063简单算法: 从前往后(或者从后往前)每次交换一个位置。当存在 ...
相关推荐
因此,如果在setjmp和longjmp之间修改了这类变量,恢复后的状态可能与实际预期不符。 3. **栈的清理**:longjmp不会自动清理在它和setjmp之间创建的局部变量。这意味着,当控制流返回到setjmp保存的点时,这部分栈...
了解如何使用setjmp和longjmp进行异常处理也很重要。 通过深入学习和练习这些C语言的经典面试题,不仅能提升编程技能,还能在面试中自信应对各种挑战,为职业发展打下坚实基础。《经典全面c面试题》这份资源无疑...
- 异常处理:学习使用setjmp和longjmp实现非局部跳转,处理异常情况。 7. **标准库与算法** - 标准库函数:熟悉常用的数学、字符串、输入输出等标准库函数。 - 算法基础:介绍排序、搜索、图论等基础算法,并...
- 异常处理:了解setjmp和longjmp函数进行非局部跳转,处理程序异常。 8. **标准库与标准输入输出** - 标准输入输出流:熟悉stdin、stdout和stderr,以及使用scanf和printf进行输入输出。 - 标准库函数:学习...
- 异常处理:了解错误处理机制,如errno和setjmp/longjmp。 3. **编程实践**: - 实战项目:通过编写简单的程序,如计算器、文本编辑器等,提升编程技能。 - 排序算法:学习冒泡排序、插入排序、选择排序、快速...
15. **异常处理**:虽然C语言没有内置的异常处理机制,但可以使用setjmp和longjmp实现类似的机制。 16. **性能优化**:通过理解C语言的底层特性,进行代码优化,例如减少不必要的内存分配,减少函数调用,合理使用...
异常处理是现代编程中重要的错误处理机制,C语言提供了setjmp和longjmp函数进行非局部跳转,但通常在微软环境中,我们会更多地使用C++的try-catch机制,因为它提供了一种更优雅的错误处理方式。 最后,C编程还强调...
在C语言的高级特性中,位操作、预处理宏、枚举、类型定义(typedef)和异常处理(setjmp/longjmp)等都需要理解。这些不仅可以提升编程效率,还能解决特定问题。 在复习过程中,历年真题的演练至关重要。通过解答...
10. **异常处理**:虽然C语言没有内置的异常处理机制,但可以通过setjmp和longjmp实现类似的功能。 在描述中,虽然内容重复,但可以推测这是一个关于C语言学习资源的集合,可能包含了教程、示例代码或者相关的学习...
- 异常处理:了解C语言中的错误处理机制,如setjmp和longjmp。 7. **C标准库** - 标准库函数:介绍常用的库函数,如数学函数、字符串处理函数、输入输出函数等。 - 标准I/O流:探讨stdio.h中的文件流操作,如...
- 异常处理:了解何时使用setjmp和longjmp。 7. **高级主题**: - 位操作:理解位掩码和位字段。 - 内存对齐:了解编译器如何处理内存对齐,以及如何影响性能。 - 并发编程:涉及到线程、互斥锁、信号量等多...
15. **异常处理**:虽然C语言本身不支持异常处理,但可以通过setjmp和longjmp模拟类似功能。 通过深入学习和实践这495个C语言问题,你将能全面地掌握C语言,并有能力解决实际开发中遇到的各种问题。无论是初学者...
实例可能涵盖动态内存分配(如malloc、calloc、realloc、free)、内存泄漏检测以及错误处理机制(如try-catch或setjmp/longjmp)的运用,这些都是提高程序稳定性和效率的关键。 总之,“c语言实例精粹.rar”是一个...
25. 异常处理:了解C语言中的错误处理方式,如setjmp和longjmp。 以上知识点构成了《C语言程序设计》的核心内容,通过学习和实践这些概念,读者将能够熟练掌握C语言,为进一步学习其他编程语言和技术打下坚实基础。...
5. 异常处理:虽然C语言没有内置的异常处理机制,但可以借助setjmp和longjmp实现类似功能。 6. 标准库函数:深入学习标准库如stdio.h、stdlib.h、string.h等中的函数,提高编程效率。 实践应用: 1. 实现算法:...
- 异常处理:探讨C语言中的错误处理方式,如setjmp和longjmp函数。 - 进程与线程:简述C语言中实现进程和线程的基本方法,如fork、exec系列函数和pthread库。 7. **实战案例** - 105个实战例子涵盖了上述各个...
3.7 异常处理:setjmp/longjmp、signal处理异常情况。 3.8 系统调用接口:通过syscalls.h头文件直接调用内核功能,如open、read、write等。 四、嵌入式C语言开发实践 4.1 嵌入式系统概述:嵌入式系统的特性、分类及...
异常处理在C语言中并不直接支持,但可以通过setjmp和longjmp函数实现类似的功能,虽然不常用,但在特定情况下非常有用。 此外,C语言的标准库提供了大量的函数,如数学运算的math.h库,字符串处理的string.h库,...
在C语言中,虽然没有像其他高级语言那样的异常系统,但我们需要掌握如何使用errno和setjmp/longjmp进行错误处理。 最后,理解C语言的内存管理,包括堆栈和堆的分配,以及内存对齐的概念,有助于写出更加高效且无...
8. **异常处理和错误检测**:学习如何使用setjmp/longjmp进行非局部跳转,以及理解和使用errno、perror等错误处理机制。 9. **安全性与权限**:理解用户和组的概念,以及访问控制列表(ACL)、文件权限和SELinux等...