如何安全地将内存转储到 SIGSEGV 处理程序中的跌落附近.C,Linux



我需要在程序崩溃的地方(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("%zxn", *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 - %dn", isRecall);
isRecall = 1;
....

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

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

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

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

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

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

相关内容

  • 没有找到相关文章

最新更新