分段错误和堆栈溢出有啥区别?

Posted

技术标签:

【中文标题】分段错误和堆栈溢出有啥区别?【英文标题】:What is the difference between a segmentation fault and a stack overflow?分段错误和堆栈溢出有什么区别? 【发布时间】:2011-02-10 17:46:54 【问题描述】:

例如,当我们调用递归函数时,连续的调用存储在堆栈中。但是,由于错误,如果它无限继续,错误是“分段错误”(如在 GCC 上看到的)。

不应该是“堆栈溢出”吗?那么两者的基本区别是什么?

顺便说一句,解释会比***链接更有帮助(经历了那个,但没有回答特定查询)。

【问题讨论】:

溢出的东西是关于编程问题的,故障的东西是关于服务器的。 oO @Pavel:SIGSEGV 与服务器有什么关系?尽管服务器应用程序可能会导致分段错误,但这与服务器管理无关,而与编程有关。 @George: serverfault.com 和嗖嗖声。 我认为这是 Posix 的限制,它不支持 SIGSTKFLT。 【参考方案1】:

堆栈溢出是 [a] 原因,分段错误是结果。


至少在 x86 和 ARM 上,“堆栈”是为放置局部变量和函数调用的返回地址而保留的一块内存。当堆栈耗尽时,将访问保留区域之外的内存。但是应用程序并没有向内核请求这块内存,因此会生成一个 SegFault 用于内存保护。

【讨论】:

【参考方案2】:

现代处理器使用内存管理器来相互保护进程。 x86 内存管理器有许多遗留功能,其中之一就是分段。分段旨在防止程序以某些方式操纵内存。例如,一个段可能被标记为只读,代码会放在那里,而另一段是读/写的,这就是你的数据所在的地方。

在堆栈溢出期间,您耗尽了分配给您的一个段的所有空间,然后您的程序开始写入内存管理器不允许的段,然后您会遇到分段错误。

【讨论】:

很确定 Unix 早在 x86 出现之前就已经使用了这个术语... @SamB 我看不出答案在哪里。 "x86 内存管理器有许多遗留功能,其中之一就是分段" != "x86 发明了分段"。 x86(段寄存器)使用的分段与操作系统执行的地址空间的“分段”完全不同。 Segmentation Fault 与段寄存器无关。此外,虽然很长一段时间都是 x86 的一部分,但段寄存器对于 x86 在现代操作系统中的工作方式仍然非常重要。 我不确定我是否理解你的意思,SoapBox。分段是在 x86 中使用段寄存器实现的概念。寄存器用于将地址空间分割成段,例如代码段、数据段、堆栈段和额外段。当您的堆栈“转义”堆栈段时,会发生堆栈溢出。我无法识别您要指出的不一致之处。 在所有现代操作系统上,段寄存器 CS、DS、SS 的设置方式使得它们被有效地忽略(额外的寄存器 ES、FS、GS 可能是用于特殊目的的例外) .分段错误不是由于 CPU 段超限,而是由于访问了无效页面。【参考方案3】:

调用堆栈正在溢出,但是溢出的结果是最终与调用相关的值被压入不属于堆栈的内存中,然后 - SIGSEGV!

【讨论】:

【参考方案4】:

堆栈溢出可以表现为显式堆栈溢出异常(取决于编译器和架构)或分段错误,即无效的内存访问。最终,堆栈溢出是堆栈空间用完的结果,而堆栈空间用完的一个可能结果是读取或写入您不应该访问的内存。因此,在许多架构上,堆栈溢出的结果是内存访问错误。

【讨论】:

以上是关于分段错误和堆栈溢出有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

ios堆栈溢出中的uuid,udid和设备令牌有啥区别

由于堆栈溢出,C 中通常会发生啥?

Java堆栈溢出的机制与原理

缓冲区溢出(vs)缓冲区溢出(vs)堆栈溢出[重复]

什么是堆栈溢出和缓冲区溢出错误? [复制]

递归 - 堆栈溢出错误