c-为什么必须对堆上的大型数据结构进行malloc



我记得我说过堆栈内存地址是如何减少的,堆的地址是如何增加的,但它们占用了相同的内存条。如果是这种情况,为什么一些大型数据结构会导致堆栈溢出,但在堆上却完全正常?

首先,忽略您所听到的历史上过于简单化的说法,您需要将malloc用于大型对象而不是自动("堆栈"(存储,这是一个根本原因:只有malloc有一个接口,它可以通过该接口报告内存的不可用性。如果您输入的函数体中有char foo[1000000000];,在现实世界中基于堆栈的实现中,是的,堆栈指针将调整1000000000,但在这一点上,谁知道它指向的是可用内存,您可以将其用作堆栈的一部分,还是在其他不相关的内存之上。有些实现(GCC的-fstack-clash-protection(会一次调整一页,并探测每一页以在第一个保护页上产生故障,从而使程序崩溃,而不是破坏无关的内存,但这也不是一个理想的结果。无论何时出现故障,您都需要一个可以报告和处理故障的渠道。

现在,谈谈为什么历史上的";堆向上生长,堆向下生长";解释错误:

  1. 只有在只有一个堆栈的情况下才有效。在多线程程序中,每个线程有一个堆栈。如果你想将它们全部定位,使它们可以以巨大的幅度向下扩展,那么你很难在32位内存空间中创建任何线程。在64位系统中,这是可能的,只是因为空间巨大,但有问题(而且大多数64位系统实际上并没有64个可用的地址位(。

  2. "堆";以及";堆栈";并不是你记忆空间中唯一的东西;堆";甚至不是一个有意义的概念。是的,历史上的malloc实现使用了增长的固定";堆范围";对于大多数分配,但通常会免除非常大的分配,而是为每个分配执行单独的mmapmunmap。但更重要的是,其他东西也存在于这个空间中——你的程序的可执行代码、可执行代码和共享库的数据段等。在现代系统中,这些代码的放置位置是随机的,以减轻程序错误的后果。这意味着它们可以被放置在你想认为的";堆的顶部";以及";堆叠的底部";,限制了任何一个可以连续生长的距离。

最新更新