gpt4 book ai didi

c - 为什么这个程序在用户信号处理程序之后没有终止

转载 作者:行者123 更新时间:2023-11-30 14:34:38 26 4
gpt4 key购买 nike

在调试下一个代码片段时,调试器返回到带有 x=5x=10/x 行,并且仍然获得 SIGFPE >.

#include <signal.h>

volatile sig_atomic_t x = 0;

void sigfpe_handler(int signum) {
x = 5;

// Notice that there is no exit()
}

int main() {
signal(SIGFPE, sigfpe_handler);
x = 10 / x;
return 0;
}
  • 这里发生了什么?
  • 处理程序实际返回到哪一点?

最佳答案

正如已经指出的,这在技术上是未定义的行为。

所发生的情况是 SIGFPE 重复出现。如果您从信号处理程序添加打印语句,您可以看到:

#include <signal.h>

volatile sig_atomic_t x = 0;

void sigfpe_handler(int signum) {
x = 5;
write(2, "Received SIGFPE\n", sizeof "Received SIGFPE\n" - 1 );
}

int main() {
signal(SIGFPE, sigfpe_handler);
x = 10 / x;
return 0;
}

这是因为当信号发生时,控制权将转移到信号处理程序,一旦返回,“主”代码就会从指令(而不是语句)恢复执行em>) 执行被中断(通过信号)。在这种情况下,它继续进行除法并发生 SIGFPE 并继续循环。

您可以看到确切的指令,它从 gdb 中重复:

Program received signal SIGFPE, Arithmetic exception.
0x00000000004005a6 in main ()
(gdb) disass
Dump of assembler code for function main:
0x000000000040057c <+0>: push %rbp
0x000000000040057d <+1>: mov %rsp,%rbp
0x0000000000400580 <+4>: sub $0x10,%rsp
0x0000000000400584 <+8>: mov $0x40054c,%esi
0x0000000000400589 <+13>: mov $0x8,%edi
0x000000000040058e <+18>: callq 0x400430 <signal@plt>
0x0000000000400593 <+23>: mov 0x20042b(%rip),%edx # 0x6009c4 <x>
0x0000000000400599 <+29>: mov %edx,-0x4(%rbp)
0x000000000040059c <+32>: mov $0xa,%eax
0x00000000004005a1 <+37>: mov %eax,%edx
0x00000000004005a3 <+39>: sar $0x1f,%edx
=> 0x00000000004005a6 <+42>: idivl -0x4(%rbp)
0x00000000004005a9 <+45>: mov %eax,0x200415(%rip) # 0x6009c4 <x>
0x00000000004005af <+51>: mov $0x0,%eax

(gdb) p $rbp
$8 = (void *) 0x7fffffffada0
(gdb) p *(int*)$rbp
$9 = 0

如果您注意到,x 的值已加载到寄存器中,并且这就是它所使用的值。这就是为什么对 x 的更改没有达到您预期的效果。

您可以执行“跳转”,然后跳过导致 FPE 的代码:

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

sigjmp_buf jbuf;

volatile sig_atomic_t x = 0;

void sigfpe_handler(int signum) {
x = 5;
write(2, "Received SIGFPE\n", sizeof "Received SIGFPE\n" - 1 );
siglongjmp(jbuf, 1);
}

int main() {
signal(SIGFPE, sigfpe_handler);
if (sigsetjmp(jbuf, 0) == 0)
x = 10 / x;
else
printf("Returned from siglongjmp\n");
return 0;
}

请阅读关于sigsetjmp/siglongjmp的手册注意事项。

关于c - 为什么这个程序在用户信号处理程序之后没有终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58890622/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com