1

让我澄清一下:我了解 new 和 delete(以及 delete[])是如何工作的。我了解堆栈是什么,并且了解何时在堆栈和堆上分配内存。

然而,我不明白的是:堆上的内存分配在哪里。我知道我们应该将堆视为这个几乎无限 RAM 的大池,但事实并非如此。

什么可以控制选择堆内存的存储位置以及它是如何选择的?

另外:“将内存返回给操作系统”这个术语是我经常遇到的。这是否意味着堆在所有进程之间共享?

我之所以关心这一切,是因为我想了解更多关于内存碎片的知识。我认为在学习如何处理内存碎片之前了解堆的工作原理是个好主意,因为我没有足够的内存分配经验,也没有 C++ 直接深入研究。

4

4 回答 4

5

内存由操作系统管理。所以答案取决于所使用的操作系统/平台。C++ 规范没有指定如何分配/释放较低级别的内存,它在生命周期中指定它。

虽然多用户桌面/服务器/手机操作系统(如 Windows、Linux、macOS、Android 等)与内存管理方式相似,但在嵌入式系统上可能完全不同。

什么可以控制选择堆内存的存储位置以及它是如何选择的?

它是负责的操作系统。正如已经说过的那样,究竟如何取决于操作系统。操作系统也可以是运行时库和最小操作系统(如includeos )的组合形式的薄层

这是否意味着堆在所有进程之间共享?

取决于观点。地址空间 - 对于多用户系统 - 通常不在进程之间共享。操作系统确保一个进程不能访问另一个进程的内存,这是通过虚拟地址空间来保证的。但是操作系统可以在所有进程之间分配整个 RAM。

对于嵌入式系统,甚至可能出现这样的情况,即每个进程都有固定数量的预分配内存(进程之间不共享),并且无法分配新内存或空闲内存。然后由开发人员自己管理预分配的内存,方法是为 stdlib 的对象提供自定义分配器,并在分配的存储中构建。

我想了解更多关于内存碎片的信息

有两种分片方式。一个是由操作系统向 C++ 运行时公开的内存地址给出的。以及硬件/操作系统方面的一个(对于嵌入式系统可能是相同的)。使用 stdlib 提供的功能无法确定操作系统可能对内存进行碎片整理的方式和形式。进程地址空间的碎片如何表现,再次取决于操作系统和使用的stdlib。

于 2020-07-18T15:24:00.350 回答
3

这些细节都没有在 C++ 规范标准中指定。只要最终结果符合标准,每个 C++ 实现都可以自由地以任何适合它的方式实现这些细节。

每个 C++ 编译器和操作系统都以自己独特的方式实现这些低级细节。这些问题没有适用于每个 C++ 编译器和每个操作系统的特定答案。随着时间的推移,很多研究都在为典型的 C++ 应用程序分析和优化内存分配和释放算法,并且有一些定制的 C++ 实现提供了每个应用程序将选择的替代内存分配算法,它认为最适合它。当然,C++ 标准没有涵盖这些。

当然,计算机中的所有内存都必须在其上运行的所有进程之间共享,并且当所有进程请求更多内存时,操作系统负责将其分配给所有进程。“将内存归还给操作系统”的所有意思是进程的内存分配器已确定它不再需要足够大的连续内存范围,以前使用过但不再使用,并通知操作系统它不再使用它它可以重新分配给另一个进程。

于 2020-07-18T15:24:05.567 回答
3

是什么决定了堆内存的分配位置?

从 C++ 程序员的角度来看:它由(C++ 语言的)实现决定。

从 C++ 标准库实现者的角度来看(作为假设某些实现可能正确的示例):由malloc哪个是 C 标准库的一部分来决定。

malloc实现者的角度来看(作为假设某些实现可能正确的示例):堆的位置通常由操作系统决定(例如,在 Linux 系统上,它可能是由sbrk. 任何单个分配的位置都由实施者决定,只要它们保持在操作系统和语言规范建立的限制范围内。


请注意,堆内存在 C++ 中称为“自由存储”。我认为这是为了避免与无关的堆数据结构混淆。


我明白堆栈是什么

请注意,C++ 语言中没有“堆栈内存”之类的东西。C++ 实现以这种方式存储自动变量的事实是实现细节。

于 2020-07-18T15:25:17.407 回答
1

堆确实在进程之间共享,但在 C++ 中,delete 关键字不会将内存返回给操作系统,而是保留它以供以后重用。分配内存的位置取决于您要访问多少内存,必须有足够的空间以及操作系统如何处理内存分配,它可以是第一个,最好的和最坏的(在 google 上阅读有关该主题的更多信息)。RAM 的名称基本上告诉您在哪里搜索您的内存 :D 但是,当您有一个小程序并多次重新启动它时,可以获得相同的内存位置。

于 2020-07-18T15:23:52.153 回答