如何安全地将内存转储到SIGSEGV处理程序内部的内部附近。 C,Linux

时间:2018-06-03 09:37:49

标签: c linux signals handler sigsegv

我需要在程序崩溃的地方旁边打印内存(SIGSEGV),但事实是当我尝试打印这个内存时,我可以再次被称为SIGSEGV。

void handler_SIGSEGV(int signal, siginfo_t *data, void *extra_data) {

for (size_t* mem = (size_t*) (data->si_addr - 5); mem < (size_t*) (data->si_addr + 5); mem++){
    printf("%zx\n", *mem);   // call new SIGSEGV
   }

    exit(1);
}

正如我在处理程序中所理解的,我可以使用volatile sig_atomic_t变量来指示信号已被触发。

volatile sig_atomic_t isRecall = 0;

void handler_SIGSEGV(int signal, siginfo_t *data, void *extra_data) {

    if (isRecall == 1){
        //second call
    }

    printf("Call - %d\n", isRecall);
    isRecall = 1;
....

但是当再次调用SIGSEGV信号时,我的函数handler_SIGSEGV由于某种原因未被调用。

为什么会这样?我怎样才能实现这样的内存输出?

1 个答案:

答案 0 :(得分:0)

si_addr是生成故障的内存地址。如果地址超出范围或进程没有读访问权限,则可能无法读取内容。例如,如果取消引用空指针,则它可能为0。

默认情况下,在处理信号时,它会被阻止,从而阻止嵌套调用。在阻塞时生成SIGSEGV会导致未定义的行为(通常是崩溃)。来自sigprocmask

  

如果生成SIGBUS,SIGFPE,SIGILL或SIGSEGV   阻止,结果是未定义的,除非信号是由...生成的   kill(2),sigqueue(3)或raise(3)。

您可以通过设置sigsetjmp / siglongjmp对或修改错误指令使用的寄存器(context->uc_mcontext.gregs)的状态来继续执行。