【问题标题】:How do I handle and move past a segfault? [duplicate]我如何处理和越过段错误? [复制]
【发布时间】:2014-03-29 22:15:42
【问题描述】:

我正在处理一个涉及链表的 C 项目,我需要对一段代码进行分段以证明它不起作用。但我的代码不会崩溃。

到目前为止,这是我的处理程序:

typedef void sigfunc(int);
sigfunc *signal(int, sigfunc*);
void Handler(int sig)
{
    if (sig == SIGSEGV)
    printf("received SegFault\n");
    signal(SIGSEGV, &Handler);
}

它需要在段错误中幸存下来。到目前为止,我得到的只是“收到 SegFault”的无限循环。提前致谢!

【问题讨论】:

  • 在信号处理程序中调用 printf() 是不安全的。 stackoverflow.com/questions/8493095/…
  • 对于您的特定用例,您最好检查每个指针的有效性(这可能需要确保所有无效指针都为空),并在段错误发生之前检测它。
  • 这个问题似乎在积累反对票......我不同意这是一个特别糟糕的问题;唯一的主要问题是正确的答案是“你不能”(不能指望提问者提前知道)。
  • 问题是“炸弹爆炸了;我的建筑物现在结构不稳定,即将倒塌。结构中可能有任意更多的炸弹,任何动作都可能触发。我如何忽略这一切并继续在那里正常生活吗?”你没有;你会尽快摆脱这种情况。进程正在下降;让它下去吧。

标签: c segmentation-fault signal-handling


【解决方案1】:

一般来说,一旦您遇到 SEGFAULT,您的流程就完成了。

在专门的术语中,它可能是可以恢复的,但是在没有敏锐地意识到自己在做什么的情况下这样做会导致重复失败、内存泄漏、无效指针以及其他问题的噩梦。

话虽如此,除非您可以重新启动进程(避免上述所有情况),否则您可以尝试使用setjmp()longjmp() 进行恢复。例如:

#include <setjmp.h>
jmp_buf restore_point;
void Handler(int sig)
{
    if (sig == SIGSEGV)
    {
        printf("received SegFault\n");
        signal(SIGSEGV, &Handler);
        longjmp(restore_point, SIGSEGV);
    }
}


void test()
{
    int fault_code = setjmp(restore_point);
    if (fault_code == 0)
    {
        // do something that might cause a segfault
    }
    else
    {
        printf("recovered from a fault; code = %d\n", fault_code);
    }
}

除了我列出的其他问题之外,另一个问题是您设置的还原点(跳转缓冲区)仅在调用setjmp()的范围终止之前才有效....您必须不 跳回终止的作用域!

本质上,longjmp() 是一个影响深远的goto,但更像是一个gobackto,因为它回到了跳转缓冲区的初始化点。它由setjmp() 函数以某种方式初始化,而不是确保setjmp() 在线性调用时返回0,并且在通过longjmp 进入时返回非零。在这种情况下,它会返回 longjmp()s 第二个参数是什么(除非该参数 == 0,在这种情况下它仍然返回非零值)。

说真的,我已经为你提供了足够的信息来让你变得危险,但不要掉以轻心......用这种方法解决问题要比解决问题容易得多,除非你已经采取非常小心并限制您使用此工具。

【讨论】:

  • 我知道一般来说这是一个可怕的想法。这是一个班级的项目。我永远不会试图在现实世界中扯这些废话。我只需要对其进行分段并生存,以便为程序返回所有正确的东西。谢谢!
猜你喜欢
  • 2018-01-06
  • 2021-05-20
  • 1970-01-01
  • 2013-03-15
  • 2020-04-25
  • 2021-11-21
  • 2014-10-31
  • 1970-01-01
  • 2012-10-03
相关资源
最近更新 更多