`
jimmee
  • 浏览: 538681 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

C语言的异常机制--setjump()和longjump()实现【转载】

阅读更多

   goto语句可以用于同一个函数内异常处理,不幸的是,goto是本地的,它只能跳到所在函数内部的标号上。为了解决这个限制,C函数库提供了setjmp()和longjmp()函数,它们分别承担非局部标号和goto作用。头文件<setjmp.h>申明了这些函数及同时所需的jmp_buf数据类型。
    1.setjmp(jbuf)设置“jump”点,用正确的程序上下文填充jmp_buf对象jbuf。这个上下文包括程序存放位置、栈和框架指针,其它重要的寄存器和内存数据。当初始化完jump的上下文,setjmp()返回0值。
    2. 以后调用longjmp(jbuf,r)的效果就是一个非局部的goto或“长跳转”到由jbuf描述的上下文处(也就是到那原来设置jbuf的setjmp()处)。当作为长跳转的目标而被调用时,setjmp()返回r (或1,如果r设为0的话)。(setjmp()不能在这种情况时返回0,否则就和设置jump点的返回值冲突了)

 

#include "apue.h"
#include <setjmp.h>

#define TOK_ADD    5

jmp_buf jmpbuffer;

int
main(void)
{
     char    line[MAXLINE];

     if (setjmp(jmpbuffer) != 0)
         printf("error");
     while (fgets(line, MAXLINE, stdin) != NULL)
        do_line(line);
     exit(0);
}

 ...

void
cmd_add(void)
{
    int     token;

    token = get_token();
    if (token < 0)    /* an error has occurred */
        longjmp(jmpbuffer, 1);
    /* rest of processing for this command */
}

 

setjump和longjump返回时对auto变量、register变量、volatile变量和静态变量的恢复情况示例。cc -O选项表示编译优化。
longjump返回时一般情况下不会恢复到setjump时的值,此种情况属于未定义。
如果你不想让anto变量的值回滚,需要加上volatile属性。

#include "apue.h"
#include <setjmp.h>

static void f1(int, int, int, int);
static void f2(void);

static jmp_buf jmpbuffer;
static int     globval;

int
main(void)
{
     int             autoval;
     register int    regival;
     volatile int    volaval;
     static int      statval;

     globval = 1; autoval = 2; regival = 3; volaval = 4; statval = 5;

     if (setjmp(jmpbuffer) != 0) {
         printf("after longjmp:\n");
         printf("globval = %d, autoval = %d, regival = %d,"
             " volaval = %d, statval = %d\n",
             globval, autoval, regival, volaval, statval);
         exit(0);
     }

     /*
      * Change variables after setjmp, but before longjmp.
      */
     globval = 95; autoval = 96; regival = 97; volaval = 98;
     statval = 99;

     f1(autoval, regival, volaval, statval); /* never returns */
     exit(0);
}

static void
f1(int i, int j, int k, int l)
{
    printf("in f1():\n");
    printf("globval = %d, autoval = %d, regival = %d,"
        " volaval = %d, statval = %d\n", globval, i, j, k, l);
    f2();
}
static void
f2(void)
{
    longjmp(jmpbuffer, 1);
}

 

    $ cc testjmp.c               compile without any optimization
    $ ./a.out
    in f1():
    globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
    after longjmp:
    globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
    $ cc -O testjmp.c            compile with full optimization
    $ ./a.out
    in f1():
    globval = 95, autoval = 96, regival = 97, volaval = 98, statval = 99
    after longjmp:
    globval = 95, autoval = 2, regival = 3, volaval = 98, statval = 99

 

分享到:
评论

相关推荐

    setjump与longjmp(异常处理机制)

    setjmp 和 longjmp 是 C 语言标准库中的两个函数,用于实现异常处理机制。它们提供了一种非本地局部跳转("non-local goto")机制,能够在程序中实现错误处理模块的调用和返回。 setjmp 函数的作用是保存程序当前的...

    c-exceptions:C语言中的简单异常

    1. **Setjump和Longjump**: C语言中,`setjmp()` 和 `longjmp()` 函数是用于实现非局部跳转的,这在一定程度上可以用来模拟异常处理。`setjmp()` 会保存当前环境(包括寄存器状态、堆栈指针等),并返回0。然后,...

    i686-5.3.0-release-posix-sjlj-rt-v4-rev0.7z

    4. **SJLJ (SetJump/LongJump) 异常处理**:"sjlj" 指的是 SetJump/LongJump 异常处理机制,它是一种在某些嵌入式和低资源环境下常用的异常处理方式,相对于其他方法可能更占用空间但效率较低。 5. **Runtime (RT)*...

    gcc-core-4.2.1-sjlj-2.tar.gz

    4.2.1是GCC的一个特定版本号,发布于2007年,而“sjlj”可能代表“SetJump/LongJump”调度,这是一种异常处理机制。 描述中同样提到了“gcc-core-4.2.1-sjlj-2.tar.gz”,这进一步确认了这是一个包含GCC核心组件的...

    HUST计网.zip

    其中的"sjlj"指的是SetJump/LongJump异常处理机制,这是一种在嵌入式系统中常见的异常处理方法。 2. **libnetsim(g++).a**:这是一个静态链接库文件,可能包含用于网络模拟的代码。"libnetsim"暗示了这可能是一个...

    windows 32 汇编语言教程

    在Windows环境中,我们可以利用API函数SetJump和LongJump实现非局部跳转,实现复杂的控制结构。 除此之外,中断处理是汇编语言在Windows环境下的另一个重要话题。系统中断,如INT 21H在DOS时代,或INT 2Eh、INT 33h...

    Loomthread-开源

    Loomthread 是一个允许多个线程并行运行的库。 它是非标准的、非 posix 的、有限的但意味着要快。 它基于信号处理程序和 setjump/longjump,速度非常快,并且提供了用于同步的互斥锁。

    CA Spectrum 命令行界面用户指南.pdf

    8. **`setjump`** - 保存模型和格局。 9. **`show`** - 显示不同类型的对象信息,如: - `showalarm` - 显示警报信息。 - `showassociation` - 显示关联信息。 - `showattributes` - 显示属性信息。 - `...

    在线厚度检测控制器说明书

    此外,控制器还具备了状态变化死区设置,即设置值“SetJUMP”,以及信号通道设置“SetChan”和滤波时间设置“SetFilt”,这些都是为了优化检测精度和稳定性。 在实际应用中,用户可以设置传感头之间的距离值...

    Thimble:用于顶针迷你游戏的Minecraft插件(déàcoudre)

    /th arena setJump 定义玩家将从何处跳转 玩耍 键入/th join 以加入竞技场。 当有足够的玩家时,游戏将自动开始。 迹象 每个拥有相关权限的玩家都可以创建可点击的标志,以替代玩家命令。 放置一个标志并在第一行...

Global site tag (gtag.js) - Google Analytics