【问题标题】:Handle/avoid stack overflow in C在 C 中处理/避免堆栈溢出
【发布时间】:2013-10-29 03:52:27
【问题描述】:

我知道您可以通过使用编译器标志和信号处理来处理整数溢出(请参阅this question 的已接受答案)。
其实你其实可以prevent it

但是我一直无法找到有关如何处理/避免堆栈溢出的任何信息:

void breakStack(int num){
     // Implied check to see if addition will cause integer overflow
     int tmp = num + 1;
     // Code to see if next call will cause a stack
     // overflow and avoid it
     breakStack(tmp);
}

或者:

void breakStack(int num){
    // Implied check to see if addition will cause integer overflow
    int tmp = num + 1;
    breakStack(tmp);
}

void stackOverFlowHandler(int signum){
    // Code to handle stack overflow
}

我找到的两个解决方案是:“不要使用递归”和​​“编译器优化可以消除尾递归,因此问题解决了”。但我正在寻找不同的解决方案。

编辑:我喜欢一种避免它的方法 (see accepted answer)。

避免解决方案:
假设你有函数的大小(例如 50 个字节), 以及堆栈上剩余的可用空间量(例如 200 字节),然后:

void tryToBreakStack(int num){
    // Implied check to see if addition will cause integer overflow
    int tmp = num + 1;
    if(functionSize>leftSpace){
        return;
    }
    tryToBreakStack(tmp);
}

现在,我可能能够获得function size with nm -S 并对其进行硬编码(我知道接受的答案表明无法完成)。附加说明:我几乎可以肯定通过调用 sizeof(tryToBreak) 或 sizeof(&tryToBreak) 无法获得此值。
此外,我也许可以设置stack size 并获得堆栈上可用空间的粗略近似值。

在我开始研究该解决方案(并且可能会看到它失败)之前,我想知道是否有另一种方法(可能更容易和更精确)。

编辑:现在我找到了避免它的方法,真正的问题是:你如何恢复 使用信号处理避免堆栈溢出。

处理方案:
我不确定当进程收到“分段错误”信号时该怎么办,它必须handle it。第一:你怎么知道它是由堆栈溢出引起的?第二:你从堆栈溢出中恢复什么?

【问题讨论】:

  • 如果你想避免stackoverflow,你不应该在stackoverflow上发布问题:p

标签: c linux signals stack-overflow callstack


【解决方案1】:

您可以定义自己的堆栈,尽管很难以完全可移植的方式进行。原则上,您可以使用 posix 线程(请参阅 pthread_set_stackaddr),因此它甚至不是特别奇特。

然后你可以使用mprotect 在你的堆栈末端创建一个红色区域(“警戒区”)。然后堆栈溢出将导致您可以处理的SIGSEGV; sigaction 处理程序将提供保护故障的地址,因此您可以检查处理程序以查看它是否属于您的红色区域之一。 (当然,您必须使用备用堆栈运行信号处理程序。请参阅SA_ONSTACK 标志和sigaltstack

从堆栈溢出中恢复(没有编译器帮助)比较棘手。

顺便说一句,函数的大小(作为由一系列机器指令组成的可重定位对象)与函数堆栈帧的大小之间没有关系。所以nm 真的对你没有任何好处。

【讨论】:

    猜你喜欢
    • 2012-08-22
    • 2020-03-08
    • 2014-07-20
    • 2010-12-04
    • 2015-11-14
    • 2010-11-30
    • 1970-01-01
    • 2016-07-12
    • 2011-11-23
    相关资源
    最近更新 更多