3

I understand that you can handle integer overflow by using compiler flags and signal handling (see accepted answer to this question).
In fact, you can actually prevent it.

However I've been unable to find any information on how to handle/avoid stack overflows:

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);
}

Or:

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
}

Two of the solutions I've found are: "Do not use recursion" and "Compiler optimizations can remove tail recursion, therefore the problem is solved". But I'm looking for a different solution.

EDIT: I fond a way to avoid it (see accepted answer).

Avoid solution:
Say you have the size of the function (e.g. 50 bytes), and the amount of free space left on the stack (e.g. 200 bytes), then:

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

Now, I might be able to get the function size with nm -S and hard code it (I know the accepted answer says it can't be done). Additional note: I'm almost sure this value can't be obtained by calling sizeof(tryToBreak) or sizeof(&tryToBreak).
In addition, I might be able to set the stack size and get a rough approximation of free space on the stack.

Before I start working on that solution (and maybe see it failing), I'd like to know if there is another way of doing it (perhaps easier and more precise).

EDIT: Now that I found a way of avoiding it, the real question is: How do you recover from a stack overflow using signal handling.

Handling solution:
I'm not sure what to do when the process receives a "segmentation fault" signal and it has to handle it. First: how do you know it was caused by a stack overflow?, and second: what do you to recover from a stack overflow?

4

1 回答 1

2

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

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

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

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

于 2013-10-20T18:58:32.137 回答