#include <stdio.h>
int doHello(){
doHello();
}
int main(){
doHello();
printf("\nLeaving Main");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当您运行此程序时,程序退出而不在屏幕上打印"Leaving Main"消息.这是Stack Overflow的情况,因为程序正在终止,但我在命令窗口中看不到任何错误消息.(跑在Windows/Cygwin /)
Q1.我没有在doHello函数中声明任何局部变量,但仍在使用堆栈.这是因为
Q2.如何在程序中调试此类案例?我不是要求调试我上面提到的无限循环.
例如:
#define SIZE 512*1024
void doOVerflow(){
char str[SIZE];
doHello();
}
void doHello(){
char strHello[256]; // stack gets filled up at this point
doNothing(); // program terminates and function doNothing does not get called
}
Run Code Online (Sandbox Code Playgroud)
编辑:
Q3.运行时堆栈中存储了哪些信息?
lea*_*der 10
通常是帧指针和返回地址.请参阅维基百科的"调用堆栈"文章.万一你好奇:
$ gcc -S test.c # <--- assembles, but does not compile, test.c; output in test.s
$ cat test.s
// [some contents snipped]
_doHello:
pushl %ebp // <--- pushes address of stack frame onto stack
movl %esp, %ebp // <--- sets up new stack frame
call _doHello // <--- pushes return value onto stack, makes call
popl %ebp // <--- pops address of stack frame off stack
ret // <--- pops return value off stack, returns to it
Run Code Online (Sandbox Code Playgroud)
为了好玩,试试"-fomit-frame-pointers":
$ gcc -fomit-frame-pointers -S test.c
$ cat test.s
// [some contents snipped]
_doHello:
call _doHello // <--- pushes return value onto stack, makes call
ret // <--- pops return value off stack, returns to it
Run Code Online (Sandbox Code Playgroud)
为了获得更多乐趣,让我们看看当我们开启优化时会发生什么:
$ gcc -fomit-frame-pointers -O4 -S test.c # <--- heavy optimization
$ cat test.s
// [some contents snipped]
_doHello:
L2:
jmp L2 // <--- no more stack operations!
Run Code Online (Sandbox Code Playgroud)
最后一个版本将永远运行,而不是退出,至少在我的设置上(cygwin,目前).
要诊断这样的问题,您可以在您喜欢的调试器(例如Microsoft Visual C++或gdb)中运行,或者检查通常由大多数系统(.core或.stackdump文件)使用这些调试器生成的stackdumps.
如果您的调试器支持这一点,您也可以在堆栈顶部附近设置硬件断点 - 任何尝试写入此变量,并且您的堆栈可能已满.某些操作系统具有其他机制来提醒您堆栈溢出.
最后,调试环境(如valgrind或Application Verifier)可能会有所帮助.