请记住,我对C和Linux来说相对较新。
对于我的一个课程,我有一个项目,我们应该找到哪个城市位于某个地理区域,我们必须使用二叉搜索树,尽管实施取决于我们。在我的特定实现中,当在树中插入新元素时,我递归地在相应的子树上调用插入函数。
我们也被告知使用Valgrind检查我们的程序,因为任何内存泄漏或错误都会对我们的成绩产生负面影响。我的程序运行得很好,我们已经给出了100,000个城市文件,但是在1,000,000个城市,Valgrind引发了我因读取/写入无效而导致的一百多万个错误,堆栈已经溢出。如果我运行具有更高堆栈大小的Valgrind,它就不会发生。
当我在没有Valgrind的情况下直接运行程序时,我没有错误。 linux会告诉我是否存在堆栈溢出?这种溢出会带来什么后果?
答案 0 :(得分:2)
为什么不试试呢?
通过以下程序,我有时会得到SIGSEGV
,有时不会:
#include <stdint.h>
uint64_t pos=261950;
int main(void)
{
volatile int a; //just some variables to use the stack
volatile int b; //and avoid too much optimizations
a=b; b=a;
if(pos)
{
pos--;
main();
}
return 0;
}
Valgrind在我的所有测试中都显示错误。通过测试发现了值261950,并且在其他安装中很可能会有所不同。
这是在GNU / Linux AMD64,Debian 8上测试的,没有任何特殊设置(我没有禁用任何类似ASLR或堆栈粉碎保护)。构建命令是:
gcc -Wall -Wextra 001.c
当变量pos
更大时,我总是看到SIGSEGV
- 消息。
当然,这里没有什么不好的事情发生,但你不能确定它是如何最终在一个更复杂的程序中,所以避免不受控制的递归。
答案 1 :(得分:2)
linux会告诉我堆栈是否有溢出?
不,如果你的堆栈溢出,Linux并不在乎。但是,它确实尝试确保超出堆栈末尾的内存地址是未映射的内存,因此库存溢出可能会出现段错误。 (这取决于每个函数的堆栈帧的大小;如果你运气不好,在堆栈上分配大型数组会产生其他症状。)
C运行时环境可能也不会告诉你,因为它需要插入额外的代码,这会降低执行速度,然后程序员会注意确保他们的堆栈不会溢出会抱怨必须支付保护您的代码免受您的错误的成本。这可能听起来很苛刻,但它基本上是C设计理念;如果你不喜欢它,还有其他语言。但是,某些编译器允许您请求插入额外的代码(使用GCC,请参阅-fstack-check
选项;另请参阅-fstack-limit-*
和-fsplit-stack
。)