【问题标题】:Catching SIGSEGV exception捕获 SIGSEGV 异常
【发布时间】:2023-02-11 01:50:13
【问题描述】:

我正在尝试使用异常处理程序来捕获错误的内存访问,但我不完全确定如何去做。我尝试用 sigaction 注册它,但我的处理程序没有触发..

#include <stdio.h>
#include <signal.h>
void handler(int sig)
{
    //exception should land here
    printf("caught exception");
    
}
int main(int argc, const char * argv[]) {

    struct sigaction act;
    
    act.sa_flags = SA_SIGINFO;
    sigemptyset(&act.sa_mask);
    act.sa_handler = handler;
    if(sigaction(SIGSEGV, &act, NULL)==-1){
        printf("Could not register handler");
    }else{
        printf("handler registered\n");
    }
    *(int*)0 = 0;//throw exception
    
    return 0;
}

一旦进入处理程序,我如何读取线程上下文寄存器?

【问题讨论】:

  • 通常,在 SIGSEGV 处理程序中您无能为力。这通常是因为内存已损坏,您尝试的任何操作都可能受到该损坏的影响。
  • stdout 只会在完整的一行之后显示文本,试试printf("caught exception\n");
  • @Barmar 我确实计划实际处理需要在某种程度上操纵文本部分的异常
  • @teapot418 我尝试放置新行但仍然没有触发..有没有一种可靠的方法可以检查实际触发的异常处理程序?而且我怎样才能读取处理程序中的寄存器?

标签: c


【解决方案1】:

您的代码的问题是您正在注册 SIGSEGV 的处理程序,这是发生分段错误时生成的信号,但您没有在代码中导致分段错误。相反,您正在取消引用空指针,这是未定义的行为,可能会导致许多后果,包括崩溃,而不会生成信号。

要导致段错误,您可以使用以下代码:

int *ptr = NULL;
*ptr = 0;

一旦进入处理程序,您就可以使用 ucontext_t 结构和 getcontext() 函数检索线程上下文,包括寄存器值。 ucontext_t 结构包含一个字段 uc_mcontext,它保存机器特定的寄存器值。以下是如何在处理程序中检索线程上下文的示例:

void handler(int sig, siginfo_t *info, void *ucontext)
{
    ucontext_t uc = (ucontext_t)ucontext;
    mcontext_t *mc = &uc->uc_mcontext;
    // access thread context registers, such as EIP/RIP or EBP/RBP
    printf("EIP/RIP: 0x%08x
", mc->gregs[REG_RIP]);
    printf("EBP/RBP: 0x%08x
", mc->gregs[REG_RBP]);
}

请注意,调用 sigaction() 函数时必须在 sa_flags 字段中设置 SA_SIGINFO 标志并将 sa_sigaction 字段设置为处理程序的地址。处理程序必须具有三个参数:int sig、siginfo_t *info 和 void *ucontext。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-24
    • 2010-09-28
    • 2017-08-18
    • 2014-12-10
    • 2018-03-01
    • 1970-01-01
    相关资源
    最近更新 更多