2014-01-15 32 views
2

练习6.2“Linux的编程接口”,由迈克尔·凯里斯克问:`longjmp`成终止函数

写一个程序,看看我们是否尝试longjmp()到一个已经终止功能会发生什么。

我在想,这个程序应该做的伎俩:

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

static jmp_buf env; 

void foo (void); 
void bar (void); 
void baz (void); 

int 
main (int argc, char *argv[]) 
{ 
    foo(); 
    bar(); 

    exit(EXIT_SUCCESS); 
} 

void 
foo (void) 
{ 
    printf("foo start\n"); 

    switch (setjmp(env)) { 
    case 0: 
     printf("foo branch 0\n"); 
     break; 
    case 1: 
     printf("foo branch 1\n"); 
     break; 
    } 

    printf("foo end\n"); 
    return; 
} 

void 
bar (void) 
{ 
    printf("bar start\n"); 

    baz(); 

    printf("bar end\n"); 
    return; 
} 

void 
baz (void) 
{ 
    printf("baz start\n"); 

    longjmp(env, 1); 

    printf("baz end\n"); 
    return; 
} 

相反,这种打印:

$ ./setjmp 
foo start 
foo branch 0 
foo end 
bar start 
baz start 
foo branch 1 
foo end 

也就是说,如果foo没有终止我本来期望的行为。这是为什么?如何修改我的程序以实现longjmp到终止函数?

+2

我不明白这个问题。你的任务是写一个程序来看看会发生什么。你做到了。你看到会发生什么。所以有什么问题? –

+2

我有一种感觉,Kerrisk先生指的是foo()中局部变量的值可能已经被foo()初始终止后使用相同堆栈空间的其他函数潦草写下。 foo()中的_control flow_在你将'longjmp()'放回去的时候仍然是一样的。 –

+1

也许这会有所帮助:如果调用'foo'传入一整堆参数,并且'foo'初始化一堆局部变量,然后在跳转后打印出当地人和形式文件,你会怎么想呢? –

回答

2

Wikipedia。带上一粒盐。

跳转到一个已经通过返回或longjmp的 终止的功能是未定义的。[6]但是,在执行跳转时,longjmp的大多数实现不会 特别销毁局部变量。由于 上下文一直存在直到其局部变量被擦除,它实际上可以通过setjmp恢复 。

幸运的是,他们确实引用了(尽管是旧的)标准。

§7.13.2.1/ 2

longjmp函数恢复由最近 调用中的setjmp宏程序中的 的与相应jmp_buf参数相同的调用保存的环境。如果还没有这样 调用,或者如果含有的setjmp 宏已经终止执行211)在临时,或者如果 调用中的setjmp宏的是标识符的范围之内的调用功能 具有可变的修改类型并且执行已经在 期间中留下了该范围,的行为未定义。

211)。例如,通过执行return语句或因为另一个 longjmp的调用已经引起早些时候组嵌套调用的 功能转移到setjmp的调用。

+0

啊,是的,那是我目睹的行为。感谢您引用标准! –