linux 会告诉我是否有堆栈溢出吗?
Would linux tell me if there was a stack overflow?
请记住,我对 C 和 linux 比较陌生。
对于我的 类 之一,我有一个项目,我们应该在其中找到哪些城市位于某个地理框中,我们必须使用二叉搜索树,尽管实现取决于我们。在我的特定实现中,当向树中插入一个新元素时,我在适当的子树上递归调用插入函数。
我们还被告知要使用 Valgrind 检查我们的程序,因为它抛出的任何内存泄漏或错误都会对我们的成绩产生负面影响。我的程序 运行 可以处理最多 100,000 个城市文件,但在 1,000,000 个城市时,Valgrind 向我抛出超过一百万个由无效 read/writes 引起的错误,堆栈已溢出。如果我 运行 具有更高堆栈大小的 Valgrind,则不会发生这种情况。
当我 运行 直接在没有 Valgrind 的情况下运行程序时,我没有收到任何错误。 linux 会告诉我是否有堆栈溢出吗?这样的溢出会造成什么后果?
为什么不测试呢?
使用以下程序,我有时会得到 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
消息。
当然,这里没有什么不好的事情发生,但是你不能确定它是如何在更复杂的程序中结束的,所以要避免不受控制的深度递归。
Would linux tell me if there was a stack overflow?
不,Linux 不在乎您是否溢出堆栈。但是,它确实做了一些尝试以确保超出堆栈末尾的内存地址是未映射的内存,因此库存溢出可能会发生段错误。 (这取决于每个函数的堆栈帧的大小;如果运气不好,在堆栈上分配大数组可能会产生其他症状。)
C 运行时环境可能也不会告诉你,因为它需要插入额外的代码,这会减慢执行速度,然后注意确保堆栈不会溢出的程序员会抱怨关于必须支付保护代码免受错误影响的成本。这听起来可能很刺耳,但这基本上就是 C 语言的设计理念;如果您不喜欢它,还有其他语言。但是,一些编译器确实允许您请求插入额外的代码(对于 GCC,请参阅 -fstack-check
选项;另请参阅 -fstack-limit-*
和 -fsplit-stack
。)
请记住,我对 C 和 linux 比较陌生。
对于我的 类 之一,我有一个项目,我们应该在其中找到哪些城市位于某个地理框中,我们必须使用二叉搜索树,尽管实现取决于我们。在我的特定实现中,当向树中插入一个新元素时,我在适当的子树上递归调用插入函数。
我们还被告知要使用 Valgrind 检查我们的程序,因为它抛出的任何内存泄漏或错误都会对我们的成绩产生负面影响。我的程序 运行 可以处理最多 100,000 个城市文件,但在 1,000,000 个城市时,Valgrind 向我抛出超过一百万个由无效 read/writes 引起的错误,堆栈已溢出。如果我 运行 具有更高堆栈大小的 Valgrind,则不会发生这种情况。
当我 运行 直接在没有 Valgrind 的情况下运行程序时,我没有收到任何错误。 linux 会告诉我是否有堆栈溢出吗?这样的溢出会造成什么后果?
为什么不测试呢?
使用以下程序,我有时会得到 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
消息。
当然,这里没有什么不好的事情发生,但是你不能确定它是如何在更复杂的程序中结束的,所以要避免不受控制的深度递归。
Would linux tell me if there was a stack overflow?
不,Linux 不在乎您是否溢出堆栈。但是,它确实做了一些尝试以确保超出堆栈末尾的内存地址是未映射的内存,因此库存溢出可能会发生段错误。 (这取决于每个函数的堆栈帧的大小;如果运气不好,在堆栈上分配大数组可能会产生其他症状。)
C 运行时环境可能也不会告诉你,因为它需要插入额外的代码,这会减慢执行速度,然后注意确保堆栈不会溢出的程序员会抱怨关于必须支付保护代码免受错误影响的成本。这听起来可能很刺耳,但这基本上就是 C 语言的设计理念;如果您不喜欢它,还有其他语言。但是,一些编译器确实允许您请求插入额外的代码(对于 GCC,请参阅 -fstack-check
选项;另请参阅 -fstack-limit-*
和 -fsplit-stack
。)