setjmp longjmp在Netbeans cygwin下崩溃Windows XP

问题描述:

以下是普渡大学CS类给出的示例代码。为了调试目的,我对原版做了很少的改动。您可以在https://www.cs.purdue.edu/homes/cs240/lectures/Lecture-19.pdf处看到原始代码。我正面临的问题在代码段下面描述。setjmp longjmp在Netbeans cygwin下崩溃Windows XP

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

int a(char* str, jmp_buf aenv) { 
    int i; 
    i = setjmp(aenv); 
    // i ++; i--; 
    printf("In func a: str = %s, i=%d\n", str, i);  #crash causing printf 
    return i; 
} 
int b(int j, jmp_buf benv) { 
    printf("In func b: j= %d\n",j); 
    longjmp(benv, j);  # segfault crash happens here, only if printf is present 
} 
int main(int argc, char** argv) { 
    jmp_buf main_env; 
    char *arr; 
    arr = (char*) malloc(100); 
    strcpy(arr, "As if called From main"); 
    if (a(arr, main_env)) { 
     printf("In main: a() returned non-zero\n"); 
     exit(EXIT_SUCCESS); 
    } 
    b(3, main_env); 
    int i=1; 
    i++; 
    printf("In main: end \n"); 
    return (EXIT_SUCCESS); 
} 

该平台是Windows XP中的Netbeans IDE 7.3和cygwin 1.7(最新版本)。当运行该程序的输出是

 In func a: str = As if called From main, i=0 
     In func b: j= 3 

当我通过调试步骤,我看到在呼叫碰撞对longjmp()。该程序运行,但在调试器,如果我删除函数a()中的printf,会给出意想不到的行为。如果我删除printf和运行程序,没有死机和输出是

 In func b: j= 
     In main: end 

我看了网络上有关的setjmp/longjmp的几个文件,我是一个专业。我的期望是,调用longjmp()会使程序状态&执行setjmp,这是另一个函数。这个函数a()应该返回3到main。所以,main()中的if条件是TRUE,我应该看到一个打印输出,说“In main:a()返回非零”。根据我对setjmp/longjmp的理解,我并不期待打印出“In main:end”,因为控制永远不会到达那里。

我怀疑这可能是一个调试器问题,因为当我通过程序(没有函数a()中的printf)时,调试器以预期的方式达到longjmp。当longjmp被执行时,调试器不会停止任何地方 - 它只是打印“In main:end”并终止程序。我在main()中引入了i ++来查看调试器是否会在打印之前停止。但是,在步入longjmp()的时候,Netbeans并没有停在那里,整个程序快速完成。

这种行为的原因是什么?在第一种情况下(当printf存在于函数a())中时,段错误的原因是什么?堆栈展开的方式是指针'str'被搞乱了吗?为什么?如果任何人有权访问UNIX机器,我希望看到该系统和程序行为的输出。感谢您的意见。

©ISO/IEC ISO/IEC 9899:201X 编程语言 - Visual C

7.13.2.1 longjmp函数

2 longjmp函数恢复由最 最近调用保存的环境在调用 程序时使用相应的jmp_buf参数调用setjmp宏...如果包含调用setjmp 宏的函数在此期间终止执行...行为未定义。

由于a()已经终止执行,在b()使用longjmp()是错误的,因此,C标准并没有规定行为要求和它是好的为程序崩溃。