如何在 SIGSEGV 处理程序中安全地转储内存。 C、Linux
How to safely dump memory near to a fall inside the SIGSEGV handler. 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("%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
不知为何没有被调用。
为什么会这样?我该如何实现这样的内存输出?
si_addr
是产生错误的内存地址。如果地址超出范围或进程没有读取权限,则可能无法读取内容。例如,如果取消引用空指针,它可能为 0。
默认情况下,在处理信号时,它会被阻止,从而防止嵌套调用。在被阻止时生成 SIGSEGV 会导致未定义的行为(通常是崩溃)。来自 sigprocmask:
If SIGBUS, SIGFPE, SIGILL, or SIGSEGV are generated while they are
blocked, the result is undefined, unless the signal was generated by
kill(2), sigqueue(3), or raise(3).
您可以通过设置 sigsetjmp
/siglongjmp
对或修改错误指令使用的寄存器 (context->uc_mcontext.gregs
) 的状态来继续执行。
我需要打印程序崩溃位置旁边的内存 (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
不知为何没有被调用。
为什么会这样?我该如何实现这样的内存输出?
si_addr
是产生错误的内存地址。如果地址超出范围或进程没有读取权限,则可能无法读取内容。例如,如果取消引用空指针,它可能为 0。
默认情况下,在处理信号时,它会被阻止,从而防止嵌套调用。在被阻止时生成 SIGSEGV 会导致未定义的行为(通常是崩溃)。来自 sigprocmask:
If SIGBUS, SIGFPE, SIGILL, or SIGSEGV are generated while they are blocked, the result is undefined, unless the signal was generated by kill(2), sigqueue(3), or raise(3).
您可以通过设置 sigsetjmp
/siglongjmp
对或修改错误指令使用的寄存器 (context->uc_mcontext.gregs
) 的状态来继续执行。