堆叠和堆碰撞时会发生什么

时间:2009-08-26 11:26:46

标签: c++ c memory stack heap

我很想知道堆栈和堆冲突时会发生什么。如果有人遇到过这种情况,请他们解释一下情况。

提前致谢。

6 个答案:

答案 0 :(得分:61)

在现代操作系统上运行的现代语言中,当您尝试增长时,您将获得堆栈溢出(欢呼!)或malloc()sbrk()mmap()将失败堆。但并非所有软件都是现代软件,所以让我们看一下故障模式:

  • 如果堆栈增长到堆中,通常C编译器将静默地开始覆盖堆的数据结构。在现代操作系统中,将有一个或多个虚拟内存保护页,可防止堆栈无限增长。只要保护页面中的内存量至少与增长过程的激活记录的大小一样大,操作系统就会保证您出现段错误。如果你的DOS在没有MMU的机器上运行,你可能已经被软管了。

  • 如果堆进入堆栈,操作系统应始终了解情况,某种系统调用将失败。 malloc()的实现几乎肯定会注意到失败并返回NULL。之后会发生什么事情取决于你。

我总是对编译器编写者希望操作系统将防护页面放在适当位置以防止堆栈溢出的意愿感到惊讶。当然,这个技巧很有效,直到你开始拥有数千个线程,每个线程都有自己的堆栈......

答案 1 :(得分:42)

这将取决于平台。在许多平台上它实际上根本不可能发生(堆和堆栈分配在不同的页面中,而且两个都不会满足。

请记住,堆向上增长和堆栈向下增长的想法只是概念性的。在非常小的系统(如运行CP / M的旧8位微处理器)和某些PIC和其他平板存储器模型系统(没有MMU或任何其他虚拟或受保护的内存支持)上,堆和堆栈可能实际上是以这种方式实现。在这种情况下,行为将是未定义的......但是一旦代码试图返回到损坏的堆栈顶部的某个地址或者从堆的一个部分到另一个部分或者间接指针,它几乎肯定会崩溃。 ..

在任何情况下,您都不会在任何现代通用工作站或服务器上看到它。您将达到资源限制并获得malloc故障,或者您将遇到虚拟内存,最终系统会自动陷入颤抖的“点击红色开关”。

答案 2 :(得分:12)

在那些时候,是时候转向Egon Spengler博士的圣人话了......

  • 博士。 Egon Spengler:我忘了告诉你一些非常重要的事情。
  • 博士。彼得·文克曼:什么?
  • 博士。 Egon Spengler:不要让堆与堆栈发生冲突。
  • 博士。 Peter Venkman:为什么?
  • 博士。 Egon Spengler:这会很糟糕。
  • 博士。 Peter Venkman:我对整个“好/坏”的事情有点模糊。你是什​​么意思,“糟糕”?
  • 博士。 Egon Spengler:试着想象所有生命,因为你知道它瞬间停止,你体内的每一个分子都以光速爆炸。
  • 博士。 Ray Stantz:完全质子逆转!
  • 博士。彼得·文克曼:那太糟糕了。好的。好的,重要的安全提示。谢谢,Egon。

答案 3 :(得分:6)

如果幸运的话,你会遇到内存不足异常或堆栈异常。如果你运气不好,程序会进入无效的内存,并引发一个错误的内存异常。如果你非常不走运,那么程序就会继续存在,并且会破坏它不应该存在的东西,你永远不知道你的程序失败的原因。

当然,宇宙可能会崩溃。

答案 4 :(得分:1)

如果发生堆栈/堆溢出,您将收到分段错误或内存分配错误。这是一个例子:

void recursiveFun ()
{
    static int i;
//  char *str= (char *)malloc (100);
    printf ("%d\t", i++);
    recursiveFun ();
// free (str);
}

假设,您调用上面的函数,它将耗尽堆栈并且程序将崩溃。现在,删除注释行并再次调用该函数,您会发现在比早期版本更少的时间和更少的递归中发生分段错误。 [在我的测试环境中,Stack Overflow在第一种情况下在5237765递归之后发生,而在第二种情况下它发生在2616325递归之后。]

答案 5 :(得分:0)

It will give stack overflow error. Or it will fail the new heap memory allocation functions like malloc().