c异常处理

转自:http://wangwiththewind.spaces.live.com/Blog/cns!B2B54F7FBFB797AA!151.entry

 

========================================================================

 

C库头文件<stdlib.h>提供了两个终止程序的函数:abort()exit()。这两个函数运行于异常生命期的45。它们都不会返回到其调用者中,并都导致程序结束。这样,它们就是结束异常处理的最后一步。

    虽然两个函数在概念上是相联系的,但它们的效果不同:

l         abort():程序异常结束。默认情况下,调用abort()导致运行期诊断和程序自毁。它可能会也可能不会刷新缓冲区、关闭被打开的文件及删除临时文件,这依赖于你的编译器的具体实现。

l         exit():文明地结束程序。除了关闭文件和给运行环境返回一个状态码外,exit()还调用了你挂接的atexit()处理程序。

    一般调用abort()处理灾难性的程序故障。因为abort()的默认行为是立即终止程序,你就必须负责在调用abort()前存储重要数据。(当我们谈论到<signal.h>时,你可以使得abort()自动调用clean up代码。)

    相反,exit()执行了挂接在atexit()上的自定义clean up代码。这些代码被按照其挂接的反序执行,你可以把它们当作虚拟析构器。通过必要的clean up代码,你可以安全地终止程序而没有留下尾巴。

   无论abort()还是exit()都不会返回到它的调用者中,且都将导致程序结束。在这个意义上来说,它们都表现为终止异常的最后一步。

    abort()exit()让你无条件终止程序。你还可以有条件地终止程序。其实现体系是每个程序员所喜爱的诊断工具:断言,定义于<assert.h>

     

       与刺激的abort()exit()相比,goto语句看起来是处理异常的更可行方案。不幸的是,goto是本地的:它只能跳到所在函数内部的标号上,而不能将控制权转移到所在程序的任意地点(当然,除非你的所有代码都在main体中)。

为了解决这个限制,C函数库提供了setjmp()longjmp()函数,它们分别承担非局部标号和goto作用。头文件<setjmp.h>申明了这些函数及同时所需的jmp_buf数据类型。

原理非常简单:

l         setjmp(j)设置“jump”点,用正确的程序上下文填充jmp_buf对象j。这个上下文包括程序存放位置、栈和框架指针,其它重要的寄存器和内存数据。当初始化完jump的上下文,setjmp()返回0值。

l         以后调用longjmp(j,r)的效果就是一个非局部的goto或“长跳转”到由j描述的上下文处(也就是到那原来设置jsetjmp()处)。当作为长跳转的目标而被调用时,setjmp()返回r1(如果r设为0的话)。(记住,setjmp()不能在这种情况时返回0。)

 

    通过有两类返回值,setjmp()让你知道它正在被怎么使用。当设置j时,setjmp()如你期望地执行;但当作为长跳转的目标时,setjmp()就从外面“唤醒”它的上下文。你可以用longjmp()来终止异常,用setjmp()标记相应的异常处理程序。

你可能感兴趣的:(c异常处理)