簡體   English   中英

為什么setjmp/longjmp

[英]Why does setjmp/longjmp

我想使用 setjmp/longjmp 在主函數中重用一些代碼(注意:這只是一個練習,而不是我在現實世界中認真計划做的事情)。 以下代碼是我想出的:

#include <stdio.h>
#include <setjmp.h>
jmp_buf jmp_body, jmp_ret;
    
void func(void)
{
    if (setjmp(jmp_ret) == 0)
        longjmp(jmp_body, 1);
}

int main()
{
    int x = 0;
    if (setjmp(jmp_body) == 1) {
        printf("Body %d\n", ++x);
        longjmp(jmp_ret, 1);
    }
    func();
    func();
    func();
    return 0;
}

我期望此代碼的工作方式如下:

  1. main()函數將記住“body”部分的位置並使用if (setjmp(jmp_body) == 1)跳過它。
  2. 在使用if (setjmp(jmp_ret) == 0)記住主體應該返回的位置后, func()調用將使用longjmp(jmp_body)臨時跳轉到主體
  3. 主體將執行並使用longjmp(jmp_ret, 1)跳轉回func()調用
  4. func() main()將按預期返回main()

因此,我期望打印的代碼如下:

Body 1
Body 2
Body 3

相反,它永遠循環不斷地執行主體,這向我表明func()調用沒有返回它應該返回的位置,而是可能返回到它自己之上,一遍又一遍地執行自己。

相比之下,以下代碼打印的正是我所期望的:

#include <stdio.h>
#include <setjmp.h>
jmp_buf jmp_body, jmp_ret;

int main()
{
    int x = 0;
    if (setjmp(jmp_body) == 1) {
        printf("Body %d\n", ++x);
        longjmp(jmp_ret, 1);
    }
    if (setjmp(jmp_ret) == 0)
        longjmp(jmp_body, 1);
    if (setjmp(jmp_ret) == 0)
        longjmp(jmp_body, 1);
    if (setjmp(jmp_ret) == 0)
        longjmp(jmp_body, 1);
    return 0;
}

if (setjmp(jmp_ret) == 0) longjmp(jmp_body, 1)放在使原始方法無效的函數調用中是什么意思?

TL/DR - 你不能跳回你跳出的函數。

7.13.2.1 longjmp函數
...
2 longjmp函數使用相應的jmp_buf參數在程序的同一調用中恢復最近一次調用setjmp宏所保存的環境。 如果沒有這樣的調用,或者如果調用來自另一個執行線程,或者如果包含setjmp宏調用的函數在中間終止了執行248) ,或者如果setjmp宏的調用在具有可變修改類型和執行的標識符的范圍在此期間離開了該范圍,行為是 undefined
248) 例如,通過執行 return 語句或因為另一個longjmp調用已導致轉移到嵌套調用集中較早的函數中的setjmp調用。
C 2011 在線選秀

當你執行longjmp(jump_body, 1); func ,您使jump_ret無效

longjmp不是雙向的 - 它展開堆棧,就好像setjmplongjmp之間的任何函數調用從未發生過一樣

您試圖將longjmpmain()堆棧返回到func() 這個沒有定義。 由於longjmp本身就是一個函數,您很可能最終將longjmp放入func ,返回地址是longjmp調用本身,因此是一個無限循環。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM