[英]C signals (SIGSEGV) why does this loop infinitely?
I was playing around with signals, and was surprised by this. 我正在玩信号,并对此感到惊讶。 Why does the program loop infinitely?
为什么程序无限循环?
#include <stdio.h>
#include <signal.h>
//I'm told that volatile tells the compiler not to cache the address of the pointer.
volatile int *i;
void seg_fault_handler(int TrapID)
{
i = malloc(sizeof(int));
puts("seg fault avoided");
}
int main()
{
signal(SIGSEGV, seg_fault_handler);
*i += 1;
return 0;
}
Note, I attempt to rectify the problem (i is NULL) by mallocing i in the handler, so my question isn't covered by this answer . 注意,我试图通过在处理程序中mallocing i来纠正问题(我是NULL),所以我的问题不在这个答案中 。
First, as one of the answers in the question you linked noted, catching an actual segfault and returning normally causes undefined behavior : 首先,作为您链接的问题中的答案之一,捕获实际的段错误并正常返回会导致未定义的行为 :
The behavior of a process is undefined after it returns normally from a signal-catching function for a SIGBUS, SIGFPE, SIGILL, or SIGSEGV signal that was not generated by kill(), sigqueue(), or raise().
在正常从信号捕获函数返回不是由kill(),sigqueue()或raise()生成的SIGBUS,SIGFPE,SIGILL或SIGSEGV信号之后,进程的行为是未定义的。
Therefore, anything is possible. 因此,一切皆有可能。
Second, volatile
does you no good here. 第二,
volatile
你在这里没有好处。 This is what gcc generates for *i += 1
: 这是gcc为
*i += 1
生成的:
movl i, %eax ; Copy the value (i.e., address) stored in i to eax
movl i, %edx ; Copy the value (i.e., address) stored in i to edx
movl (%edx), %edx ; Copy the value at the address in edx into edx <--- segfault here
addl $1, %edx ; Add 1 to edx
movl %edx, (%eax) ; Store the value in edx to the address in eax
Even if you declare i
volatile itself ( volatile int * volatile i;
), it wouldn't work. 即使你声明
i
自己挥动( volatile int * volatile i;
),它也行不通。 Now the compiler actually reads from i
only a single time: 现在编译器实际上只从
i
那里读取一次:
movl i, %eax ; Copy the value (i.e., address) stored in i to eax
movl (%eax), %edx ; Copy the value at the address in eax into edx <--- segfault here
addl $1, %edx ; Add 1 to edx
movl %edx, (%eax) ; Store the value in edx to the address in eax
Returning from the signal handler causes the segfaulting instruction to be re-executed, but your changes to i
in the signal handler will not affect the value in edx, so it still segfaults into an infinite loop. 从信号处理程序返回会导致重新执行segfaulting指令,但是在信号处理程序中对
i
的更改不会影响edx中的值,因此它仍然会陷入无限循环。 The OS doesn't know how the value in edx come about and will not recompute it (in this case, by loading i again) for you. 操作系统不知道edx中的值是如何产生的,也不会重新计算它(在这种情况下,通过再次加载i)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.