2014-04-23 83 views
0

以下是普渡大學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機器,我希望看到該系統和程序行爲的輸出。感謝您的意見。

回答

0

©ISO/IEC ISO/IEC 9899:201X 編程語言 - Visual C

7.13.2.1 longjmp函數

2 longjmp函數恢復由最 最近調用保存的環境在調用 程序時使用相應的jmp_buf參數調用setjmp宏...如果包含調用setjmp 宏的函數在此期間終止執行...行爲未定義。

由於a()已經終止執行,在b()使用longjmp()是錯誤的,因此,C標準並沒有規定行爲要求和它是好的爲程序崩潰。