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

mah*_*esh 55 c c++ memory heap stack

我很想知道堆栈和堆碰撞时会发生什么.如果有人遇到过这个,请他们解释一下这个场景.

提前致谢.

Nor*_*sey 62

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

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

  • 如果堆增长到堆栈中,操作系统应始终了解情况,某种系统调用将失败.执行malloc()几乎肯定会注意到失败和回报NULL.之后会发生什么事取决于你.

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

  • 即使使用单个线程,也可能会出现未检测到的堆栈堆冲突:https://gcc.gnu.org/ml/gcc-help/2014-07/msg00076.html(尽管这在实践中不太可能发生,也许除非在特定攻击的情况下)。GCC 手册页建议在多线程程序中使用 `-fstack-check` 标志(并且这个标志也允许在我的示例中检测冲突)。 (2认同)

Jim*_*nis 42

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

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

无论如何,您不会在任何现代通用工作站或服务器上看到它.您将达到资源限制并获得malloc故障,否则您将遇到虚拟内存,最终系统会自动陷入"点击红色开关"的颤抖状态.

  • +1对于欢闹和使用,"不是两个人". (8认同)

Pau*_*xon 12

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

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


Pre*_*gha 6

如果幸运的话,会出现内存不足或堆栈异常.如果你运气不好,程序将进入无效内存并引发错误的内存异常.如果你非常不走运,那么程序会继续进行,并且会破坏它不应该的东西,你永远不知道为什么你的程序失败了.

最后当然宇宙可能会破裂.

  • +1 MS-DOS 世界已经破裂,但我们还没有看到繁荣 (2认同)