我当时正在玩信号,对此感到惊讶。为什么程序无限循环?
#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;
}
请注意,我尝试通过在处理程序中分配i来纠正问题(i为NULL),因此此答案未涵盖我的问题。
首先,正如您所链接问题的答案之一指出的那样,捕获实际的段错误并返回通常会导致未定义的行为:
进程的行为通常是从不是由kill(),sigqueue()或raise()生成的SIGBUS,SIGFPE,SIGILL或SIGSEGV信号的信号捕获函数返回后,进程的行为是不确定的。
因此,一切皆有可能。
第二,volatile
你在这里不好吗?这就是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
即使您声明i
volatile本身(volatile int * volatile i;
),也不起作用。现在,编译器实际上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
从信号处理程序返回将导致重新执行segfaulting指令,但是您i
对信号处理程序进行的更改不会影响edx中的值,因此它仍会分段进入无限循环。操作系统不知道edx中的值是如何产生的,因此不会为您重新计算(在这种情况下,通过再次加载i)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句