我需要在程序崩溃的地方旁边打印内存(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
由于某种原因未被调用。
为什么会这样?我怎样才能实现这样的内存输出?
答案 0 :(得分:0)
si_addr
是生成故障的内存地址。如果地址超出范围或进程没有读访问权限,则可能无法读取内容。例如,如果取消引用空指针,则它可能为0。
默认情况下,在处理信号时,它会被阻止,从而阻止嵌套调用。在阻塞时生成SIGSEGV会导致未定义的行为(通常是崩溃)。来自sigprocmask:
如果生成SIGBUS,SIGFPE,SIGILL或SIGSEGV 阻止,结果是未定义的,除非信号是由...生成的 kill(2),sigqueue(3)或raise(3)。
您可以通过设置sigsetjmp
/ siglongjmp
对或修改错误指令使用的寄存器(context->uc_mcontext.gregs
)的状态来继续执行。