很多读者在此之前可能根本没有使用或者听说过C语言的异常处理,印象中都是C++或者java才有的东西,C语言怎么会有异常处理呢?当然估计在大学出于一般的性的学习考试之类的话老师几乎是不会提及C语言的异常处理的,那么到底什么是异常处理?C语言中又该如何来实现异常处理呢?那么我们今天就讲解一种典型的实现C语言异常处理的方法,以setjmp()函数和longjmp()函数实现的异常处理,我尽可能的把它们是怎样实现异常处理方法讲解清楚,希望接下来的内容对你有所帮助,让你学到一些新的东西。
首先我们来了解下异常处理,异常是一个在程序执行期间发生的事件,它中断正在执行的程序的正常的指令流,而我们的异常处理功能提供了处理程序运行时出现的任何意外或异常情况的方法。
接下来我们先看看setjmp()函数和longjmp()函数实现C语言异常处理。
setjmp()函数原型:
int ( jmp_buf env );
如果我们打开源代码会发现在setjmp()函数中涉及到很多的寄存器的操作,如Ebp、Ebx、Edi、Esi、Esp、 Eip等等,在此就不一一例举了,我们无非是想向读者说明一个问题,那就是在调用setjmp()函数的过程中保存程序的当前运行时的堆栈环境,保存这些堆栈环境有什么用呢?接下来我们看看longjmp()函数。
longjmp()函数原型:
void longjmp( jmp_buf env, int value );
刚刚上面的函数功能是保存程序执行时候的堆栈环境,我们发现在longjmp()函数里也有一个jmp_buf类型的env变量,这其实是为了保证接下来调用longjmp时,会根据这个曾经保存的变量来恢复先前的环境,并且当前的程序控制流,会因此而返回到最初调用setjmp()函数时的程序执行点。此时,在接下来的控制流的例程中,所能访问的所有的变量,包含了longjmp函数调用时所拥有的变量。我们就这样说读者可能就得有点抽象了,那我们还是来看看一段代码后再来分析吧,在此特地给出了一个简单的代码,由易到难的来分析。
|
运行结果为:
|
看了上面的运行结果,现在我们接着上面的讲,在一开始的部分我们并没有具体的交代setjmp()函数和longjmp()函数的返回值和参数的具体含义。两个函数中的env变量保存的是调用setjmp()函数的时候当前运行程序的堆栈信息,而longjmp()函数的调用就是根据在调用setjmp()函数的时候的堆栈信息返回到最初调用setjmp()函数的地方,而其中的第二个参数就是此刻setjmp()函数的返回值,但是值得注意的就是调用longjmp()函数之后setjmp函数返回的值必须是非零值,如果longjmp传送的value参数值为0,那么实际上setjmp返回的值是1。一开始我们调用setjmp()函数的时候,它的返回值为0,之后再调用longjmp()函数的时候,通过设定longjmp()函数的第二个参数来设定它的返回值。