【问题标题】:How to make the SIGSEGV handler be launched on an alternate stack for stack overflow case only?如何使 SIGSEGV 处理程序仅在堆栈溢出情况下在备用堆栈上启动?
【发布时间】:2018-02-01 22:55:06
【问题描述】:

我的应用使用 SIGSEGV(Segmentation Violation)信号处理程序(在 sigaction() 注册)。

当我的应用程序访问 NULL 指针时,我的 SIGSEGV 处理程序获得一个控制,打印(到控制台并记录)违规线程的堆栈跟踪,并调用导致核心转储(崩溃转储)的默认信号处理程序一代。因此,当测试人员报告崩溃时,我很快会在日志中看到有问题的线程堆栈跟踪(没有分析核心转储)。

但是在 堆栈溢出 的情况下,我的信号处理程序未启动,应用程序崩溃(带有静默日志)。在分析核心转储时,我(或我的同事)发现崩溃发生在正确代码的中间。理解堆栈溢出是崩溃的原因需要很长时间。所以我希望在日志中至少有一条消息“堆栈溢出”(以防堆栈溢出)。

在阅读SIGALTSTACK(2) 手册页(注意部分)时,我意识到我的信号处理程序是在有问题的线程的堆栈上调用的,这就是为什么在堆栈溢出的情况下无法调用信号处理程序(没有堆栈以调用信号处理程序)。 但是,可以在备用堆栈上运行信号处理程序。这将让我的信号处理程序记录消息“堆栈溢出”。

但是手册页让我认为,如果我将 SIGSEGV 处理程序切换为使用备用堆栈,则处理程序将始终在备用堆栈上执行,并且将无法记录 NULL 指针的违规线程堆栈跟踪-访问案例。

因此问题是:“如何使 SIGSEGV 处理程序在备用堆栈上启动仅适用于堆栈溢出情况(以及在当前活动堆栈上适用于所有其他情况)?”


要获取堆栈跟踪,我使用以下调用:backtrace()backtrace_symbols()abi::__cxa_demangle()

【问题讨论】:

  • 在“正常”sigsegv 的情况下如何获取堆栈跟踪?
  • @user58697,我已经更新了问题,见底线。

标签: c++ c linux


【解决方案1】:

不要重置处理程序并在空指针取消引用时重新引发SIGSEGV,而是检查您是否正在替代堆栈上运行,如果是,请使用sigaction关闭备用堆栈,然后重新引发信号并返回。然后,您将在主堆栈上处理新信号。

当然最好确保不会发生堆栈溢出。不要创建非平凡大小的基于堆栈的缓冲区,也不要使用递归。

【讨论】:

    猜你喜欢
    • 2012-04-23
    • 1970-01-01
    • 2019-05-18
    • 2010-12-19
    • 1970-01-01
    • 2013-10-29
    • 2012-05-01
    • 1970-01-01
    • 2016-05-06
    相关资源
    最近更新 更多