【问题标题】:How to safely dump memory near to a fall inside the SIGSEGV handler. C, Linux如何在 SIGSEGV 处理程序内安全地转储内存。 C、Linux
【发布时间】:2018-11-12 20:53:20
【问题描述】:

我需要在程序崩溃的地方(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 由于某种原因没有被调用。

为什么会这样?以及如何实现这样的内存输出?

【问题讨论】:

    标签: c linux signals handler segmentation-fault


    【解决方案1】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-10
      • 2011-02-11
      • 2013-01-05
      • 1970-01-01
      • 2016-10-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多