c mock try catch

Non-local jump statements---setjmp and longjmp functions. Non-local means that this is not a jump implemented by an ordinary C language goto statement within a function, but skips several call frames on the stack and returns to a function on the current function call path.
#include <setjmp.h>
Int setjmp(jmp_buf env);
   Return value: 0 if called directly, non-zero if returned from longjmp call
Void longjmp(jmp_buf env, int val);
    at the desired position Call setjmp, this location is in the main function, because the function is called directly, so its return value is 0. The type of the setjmp parameter evn is a special type jmp_buf, this data type is some form of array, which is stored in the call All information that can be used to restore the stack state during longjmp. Because the env variable needs to be referenced in another function, the canonical way of doing it is to define the env variable as a global variable.
   When an error is detected, the longjmp function is called with two arguments, the first is the env used when calling setjmp, and the second is val with a non-zero value, which will be the value returned from setjmp. The reason for using the second parameter is that there can be multiple longjmps for one setjmp.
    Below we can see a simple example
:

#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>

void fun1(void);
void fun2(void);
 jmp_buf jmpbuffer;
void main(void)
{
    int i = 0;
    int j = 0;
    i = setjmp(jmpbuffer);
    if(i==0)
    {
        printf("first run/n");
        fun1();
        fun2();
    }
   else
   {
     switch(i)
     {
       
     case 1:
       printf("In fun1 /n");
     break;
   case 2:
     printf("In fun2/n");
     break;
   default:
     printf("unkown error/n");
     break;
     }
          exit(0);
   }
    return 1;


void fun1(void)
{
    char *s = "hello";
    char *s1 = "Hello";
    if(strcmp(s,s1)!=0)
    longjmp(jmpbuffer,1);
}

void fun2(void)
{
    char *s = "world";
    if(strcmp(s,"World")!=0)
    longjmp(jmpbuffer,2);
}

The result of running this function is:

root@root:~/program/test_program$ ./jmp_test
first run
In fun1

   在使用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

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327075817&siteId=291194637