在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問(wèn)答/C  Office/ C 語(yǔ)言信號(hào)處理程序中的非本地跳轉(zhuǎn) ?

C 語(yǔ)言信號(hào)處理程序中的非本地跳轉(zhuǎn) ?

參考 Exceptions in C with Longjmp and Setjmp 寫(xiě)了下面一段程序:

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

jmp_buf ex_buf__;

#define TRY do{ if(!setjmp(ex_buf__)) {
#define CATCH } else {
#define ETRY } } while(0)
#define THROW longjmp(ex_buf__, 1)

void sigint_handler(int sig) {
  THROW;
}


int main(void) {
  if (signal(SIGINT, sigint_handler) == SIG_ERR) {
    return 0;
  }

  TRY {
    while (1) {
      printf("Run...\r");
    }
    /* raise(SIGINT); */
  } CATCH {
    printf("KeyboardInterrupt");
  }
  ETRY;

  return 0;
}

本來(lái)是希望在程序運(yùn)行時(shí), 按下 Ctrl-C 后會(huì)的到輸出: KeyboardInterrupt.

然而實(shí)際運(yùn)行的時(shí)候程序崩潰了。 崩潰前的輸出依然是 Run....

假如將 while 部分用 raise(SIGINT) 替代可以得到期望的結(jié)果。

這是為什么呢 ? 是不是和死循環(huán)有什么關(guān)系 ?

編譯環(huán)境:

  • 編譯器:

    gcc version 7.2.0 (x86_64-win32-seh-rev1, Built by MinGW-W64 project)
    clang version 5.0.1 (tags/RELEASE_501/final)
    Target: x86_64-pc-windows-msvc
    Thread model: posix

    兩個(gè)的運(yùn)行結(jié)果是一樣的。

  • 操作系統(tǒng):

    Microsoft Windows 7
回答
編輯回答
萌二代

除非浮點(diǎn)數(shù)異常,Windows 明令禁止在信號(hào)處理函數(shù)中調(diào)用 longjmp,否則進(jìn)程將崩潰(異常 C0000029 INVALID_UNWIND_TARGET)。

一定要在 signal handler 中調(diào)用 longjmp 的話,要避開(kāi) msvcr 的實(shí)現(xiàn)庫(kù),可改用 gcc 的 __builtin__longjmp,如下

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

jmp_buf ex_buf__;

void sigint_handler(int sig)
{
    __builtin_longjmp(ex_buf__, 1);
}

int main(void)
{
    if (signal(SIGINT, sigint_handler) == SIG_ERR) {
        return 0;
    }

    if (!__builtin_setjmp(ex_buf__)) {
        while (1) {
            printf("Run...\r");
        }
    } else {
        // 這里不能調(diào)用 print() 或 fprintf(stdout, ...)
        fprintf(stderr, "KeyboardInterrupt\n");
    }
    
    return 0;
}

注意:調(diào)用 __builtin_longjmp 之后不能再使用 printf,因?yàn)樾盘?hào)中斷已經(jīng)破壞它的內(nèi)部狀態(tài)。繼續(xù)往標(biāo)準(zhǔn)輸出(stdout)打印,將導(dǎo)致進(jìn)程崩潰。

當(dāng)然,最好不要在 signal handler 中使用 longjmp,以及其他非異步安全的函數(shù),以免產(chǎn)生安全漏洞,或各種奇怪問(wèn)題。

參考資料
[1]. https://docs.microsoft.com/en...
[2]. https://wiki.sei.cmu.edu/conf...

2017年8月28日 03:58