C 为什么在用户';s信号处理器
调试下一个代码段时,调试器返回到带有C 为什么在用户';s信号处理器,c,concurrency,signals,C,Concurrency,Signals,调试下一个代码段时,调试器返回到带有x=5的行x=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;
x=5
的行x=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;
}
#包括
挥发性sig_原子x=0;
无效sigfpe_处理程序(int signum){
x=5;
//请注意,没有出口()
}
int main(){
信号(SIGFPE,SIGFPE_处理器);
x=10/x;
返回0;
}
- 这里发生了什么李>
- 处理程序实际返回到哪一点
SIGFPE
安装一个信号处理程序,然后执行一些操作,使系统生成该信号
从POSIX规范:
进程的行为在正常情况下从不是由kill()、sigqueue()或raise()生成的SIGBUS、SIGFPE、SIGILL或SIGSEGV信号的信号捕获函数返回后是未定义的
C标准中也有类似的措辞。所以接下来发生的事情是无法控制的,因为它是未定义的行为。您的程序可能会继续,可能会进入无限循环,等等
此外,如果您希望在处理程序中对变量所做的更改能够可靠地、可移植地显示在处理程序之外,那么您的
x
变量需要是volatile sig_atomic_t
类型(假设所述处理程序不会像本例中那样导致未定义的行为)。C11无锁原子类型也可以。如前所述,这在技术上是未定义的行为
发生的情况是,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;
}
如果您注意到,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;
}
#包括
#包括
#包括
#包括
sigjmp_buf jbuf;
挥发性sig_原子x=0;
无效sigfpe_处理程序(int signum){
x=5;
写入(2,“接收到的SIGFPE\n”,sizeof“接收到的SIGFPE\n”-1);
siglongjmp(jbuf,1);
}
int main(){
信号(SIGFPE,SIGFPE_处理器);
if(sigsetjmp(jbuf,0)==0)
x=10/x;
其他的
printf(“从siglongjmp返回\n”);
返回0;
}
有关注意事项,请阅读手册
#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;
}