分割错误和堆栈溢出有什么区别?

39
例如,当我们调用一个递归函数时,连续的调用将被存储在堆栈中。然而,如果由于错误导致它无限制地继续下去,错误就会是“分段错误”(在GCC上看到)。
这难道不应该是“堆栈溢出”吗?那么两者之间的基本区别是什么?
顺便说一句,解释比维基百科链接更有帮助(经过搜索,但没有特定查询的答案)。

5
Overflow的内容涉及编程问题,Fault的内容涉及服务器。oO - P Shved
2
@Pavel:SIGSEGV与服务器有什么关系?虽然服务器应用程序可能会导致分段错误,但这与服务器管理没有任何关系,而与编程有关。 - Nathan Osman
6
@George: http://serverfault.com/ 和 Whoosh。 - kennytm
我认为这是一个 POSIX 的限制,它不支持 SIGSTKFLT。 - Hans Passant
4个回答

68

堆栈溢出是导致分段错误的原因。


至少在x86和ARM上,“堆栈”是为了放置本地变量和函数调用返回地址而保留的一块内存。当堆栈耗尽时,将访问保留区域外的内存。但是应用程序没有请求内核分配此内存,因此生成一个分段错误以进行内存保护。


6
现代处理器使用内存管理器来保护进程之间的安全。x86内存管理器有许多遗留特性之一就是分段。分段的目的是防止程序以某种方���操纵内存。例如,一个段可能被标记为只读,代码将被放置在其中,而另一个段则是可读/写的,那里是您的数据所在。
在栈溢出期间,您会耗尽分配给其中一个段的所有空间,然后您的程序开始写入内存管理器不允许的段,然后您就会收到一个分段错误。

1
相信 Unix 在接近 x86 之前很久就使用了这个术语... - SamB
3
@SamB 我没有看到答案声称有其他情况。"x86内存管理器有许多传统功能,其中之一是分段" != "x86发明了分段"。 - JBentley
2
x86使用的分段(段寄存器)与操作系统执行的地址空间的“分段”完全不同。段错误与段寄存器无关。此外,尽管长期以来是x86的一部分,但段寄存器在现代操作系统中仍非常重要。 - SoapBox
我不确定我理解你的观点,SoapBox。在x86中,分段是使用段寄存器实现的概念。这些寄存器用于将地址空间分割成段,例如代码段、数据段、堆栈段和额外段。当你的堆栈“逃离”堆栈段时,就会发生堆栈溢出。我很难确定你试图指出的不一致之处。 - ajs410
在所有现代操作系统中,段寄存器CS、DS和SS的设置方式使它们被有效地忽略(额外的寄存器ES、FS、GS可以是用于特殊目的的例外)。分段错误不是由于超出CPU段而导致的,而是由于访问无效页面引起的。 - user253751

4

堆栈溢出可能表现为明确的堆栈溢出异常(取决于编译器和体系结构),也可能表现为分段错误,即无效内存访问。最终,堆栈溢出是由于堆栈空间不足而导致的,堆栈空间不足的一个可能结果是读取或写入您不应访问的内存。因此,在许多体系结构上,堆栈溢出的结果是内存访问错误。


3
调用栈正在溢出,然而溢出的结果是最终与调用相关的值被推入不属于堆栈的内存中,然后会出现“SIGSEGV”错误!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接