当堆栈和堆碰撞时会发生什么
我很好奇当堆栈和堆碰撞时会发生什么。如果有人遇到过这种情况,请他们解释一下情况。
I am curious to know what happens when the stack and the heap collide. If anybody has encountered this, please could they explain the scenario.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
在现代操作系统上运行的现代语言中,您将遇到堆栈溢出(万岁!)或
malloc()
或sbrk()
或mmap( )
当您尝试增加堆时将会失败。但并不是所有的软件都是现代的,所以让我们看看失败模式:如果堆栈增长到堆中,典型的 C 编译器将默默地开始覆盖堆的数据结构。在现代操作系统上,会有一个或多个虚拟内存保护页,以防止堆栈无限增长。只要保护页中的内存量至少与增长过程的激活记录的大小一样大,操作系统就会保证出现段错误。如果您在没有 MMU 的机器上运行 DOS,您可能会被淹没。
如果堆增长到堆栈中,操作系统应该始终了解这种情况,并且某种系统调用将会失败。
malloc()
的实现几乎肯定会注意到失败并返回NULL
。之后发生的事情取决于您。我总是对编译器编写者愿意希望操作系统放置保护页以防止堆栈溢出感到惊讶。当然,这个技巧很有效,直到你开始拥有数千个线程,每个线程都有自己的堆栈......
In a modern languages running on a modern OS, you'll get either a stack overflow (hurray!) or
malloc()
orsbrk()
ormmap()
will fail when you try to grow the heap. But not all software is modern, so let's look at the failure modes:If the stack grows into the heap, the typically C compiler will silently start to overwrite the heap's data structures. On a modern OS, there will be one or more virtual memory guard pages which prevent the stack from growing indefinitely. As long as the amount of memory in the guard pages is at least as large as the size of the growing procedure's activation record, the OS will guarantee you a segfault. If you're DOS running on a machine with no MMU, you're probably hosed.
If the heap grows into the stack, the operating system should always be aware of the situation and some sort of system call will fail. The implementation of
malloc()
almost certainly notices the failure and returnsNULL
. What happens after that is up to you.I'm always amazed at the willingness of compiler writers to hope that the OS puts guard pages in place to prevent stack overflow. Of course, this trick works well until you start having thousands of threads, each with its own stack...
这将取决于平台。在许多平台上,这实际上根本不可能发生(堆和堆栈分配在不同的页面中,并且两者不会相遇。
请记住,堆向上增长和堆栈向下增长的想法只是概念性的。在非常小的系统(例如运行 CP/M 的旧 8 位微处理器)以及某些 PIC 和其他平面内存模型系统(没有 MMU 或任何其他虚拟或受保护内存支持的系统)上,堆和堆栈实际上可能是在这种情况下,行为将是未定义的......但一旦代码尝试返回到损坏的堆栈顶部的某个地址或遵循来自堆的一部分的间接指针,它几乎肯定会崩溃。到另一个或......
无论如何,您不会在任何现代的通用工作站或服务器上看到它,您将达到资源限制并获得 malloc 失败,或者您将遇到虚拟内存,最终系统将出现这种情况。把自己撞成一堆颤抖的“按下红色开关”。
This would be platform dependent. On many platforms it actually can't happen at all (the heap and stack are allocated in different pages and ne'r the twain shall meet.
Keep in mind that the idea of the heap growing upward and the stack growing downward is only conceptual. On very small systems (like the old 8-bit micros that ran CP/M) and on some PICs and other flat memory model systems (those without an MMU nor any other virtual or protected memory support) then the heap and stack might be actually implemented this way. In that case the behavior would be undefined ... but it would almost certainly crash as soon as the code tried to return to some address on the top of the corrupted stack or follow an indirect pointer from one part of the heap to another or ...
In any event you won't see it on any modern, general purpose workstation or server. You'll hit a resource limit and get malloc failures, or you'll run into virtual memory and eventually the system will thrash itself into quivering pile of "hit the red switch."
在这样的时刻,是时候求助于埃贡·斯宾格勒博士的圣言了……
In times like those it's time to turn to the sage words of Dr Egon Spengler....
如果幸运的话,您会遇到内存不足异常或堆栈异常。如果运气不好,程序会进入无效内存并抛出错误内存异常。如果你非常不幸,程序会继续执行并丢弃一些不应该的东西,你永远不知道为什么你的程序会失败。
当然,宇宙最终可能会破裂。
You get an out of memory exception or stack exception if you are lucky. If you are unlucky the program heads off into a invalid memory and either throws a bad memory exception. If you are extremely unlucky the program carries on and trashes something it shouldn't and you never know why your program failed.
Finally of course the universe may crack.
如果发生堆栈/堆溢出,您将收到分段错误或内存分配错误。这是一个例子:
假设您调用上面的函数,它将耗尽堆栈并且程序将崩溃。现在,删除注释行并再次调用该函数,您会发现分段错误发生的时间比早期版本更少,递归也更少。
[在我的测试环境中,在第一种情况下,堆栈溢出发生在 5237765 次递归之后,而在第二种情况下,它发生在 2616325 次递归之后。]
You will get segmentation fault or memory allocation error if stack/heap overflow occurs. Here is an example :
Suppose, you call above function, it will run out of stack and program will crash. Now, remove the commented lines and call the function again, you will find segmentation fault occurs in less time than and less recursion than earlier version.
[ In my test environment, Stack Overflow happened after 5237765 recursion in first case, whereas in second scenario it occured after 2616325 recursion.]
它将给出堆栈溢出错误。否则,新的堆内存分配函数(如 malloc())将会失败。
It will give stack overflow error. Or it will fail the new heap memory allocation functions like malloc().