简体   繁体   English

C信号(SIGSEGV)为什么会无限循环?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM