"Memory Fragmentation"这仍然是一个问题?
"Memory Fragmentation" is it still an issue?
我有点困惑。在操作系统课程中,我们被告知所有操作系统都通过分页或分段来处理内存碎片,并且根本没有连续的物理内存分配。操作系统使用不同级别的寻址(逻辑/物理(来避免连续的内存分配。现在这里有很多关于它的讨论。我的问题是: 在支持逻辑寻址的操作系统的 C++ 编程中,这个问题是否真实存在(任何进程是否仅仅因为内存碎片而崩溃(? 如果是,为什么每个操作系统首先都试图避免连续寻址?
有 2 层:虚拟进程地址空间中的碎片和物理内存中的碎片。
如果您查看任何现代应用程序,您可以看到由于内存未释放到操作系统,其内存使用量如何随着时间的推移而增长。您可以说这是由其他原因引起的,但内存碎片(例如分配的内存块的非连续位置(是造成这种情况的核心原因。简而言之,内存分配器拒绝向操作系统释放内存。
如果您对物理内存中的碎片感兴趣,那么即使内存组织在页面中,仍然需要分配物理上连续的内存块。例如,如果您需要避免虚拟内存开销,则可能需要使用大页面(Linux中的"大页面"(。x86_64支持 4KiB、2MiB 和 1GiB 页面。如果没有所需大小的连续物理内存,您将无法使用它们。
如果您所说的操作系统是指"内核",那么它无法帮助您解决进程地址空间中发生的碎片(堆碎片(。C 库应该尽量避免碎片,不幸的是,它并不总是能够这样做。请参阅链接的问题。
如果内存分配器中至少分配了某些内容,则通常无法释放大块内存。对此有一个部分解决方案,它利用页面中的虚拟内存组织 - 所谓的"无惰"机制,以Linux和BSD上的MADV_FREE
和Windows上的DiscardVirtualMemory
表示。当您有一大块内存仅部分使用时,您可以通知内核不再需要该内存的一部分,并且可以在内存压力下将其收回。这是在内存压力下延迟完成的,并且仅在内存压力下完成,因为内存释放非常昂贵。但是出于性能原因,许多内存分配器仍然不使用它。
所以你的问题的答案 - 这取决于你对程序效率的关心程度。大多数程序并不关心,因为标准分配器只是为他们完成工作。当标准分配器无法有效地完成其工作时,某些程序可能会受到影响。
操作系统不会避免连续的内存分配。在顶层,您拥有硬件和软件。硬件资源有限,在这种情况下是物理内存。为了共享资源并避免用户程序处理其共享,发明了虚拟寻址层。它只是将连续的虚拟寻址空间映射到稀疏的物理区域。换句话说0x10000虚拟地址可以在一个进程中指向0x80000物理地址,而在另一个进程中指向0xf0000。
分页和交换意味着将某些页面或整个应用程序内存写入磁盘,然后在某个时候将其恢复。它之后很可能有不同的物理页面映射。
因此,您的程序将始终看到连续的虚拟寻址空间,这在物理硬件空间中实际上是碎片化的。顺便说一句,它是以恒定的块大小完成的,并且没有浪费或未使用的内存孔。
现在,由new
/malloc
函数引起的第二级碎片与您分配和删除不同大小的内存有关。这会在虚拟空间中对堆进行分段。这些功能确保尽可能少的浪费。
因此,在您的通用C++(或任何其他语言(编程中,您不关心任何内存碎片。您分配的所有块都保证在虚拟空间中是连续的(不一定在物理空间中(。
- 在决定是通过参考还是通过价值时,尺寸真的是一个问题吗
- 在用于格式4的arm模拟器中实现功能时的一个问题
- 为什么在分配给成员变量之前获取unique_ptr的返回是一个问题?
- 我在使用 boost::serialization 时遇到了一个问题,我的代码在 Linux 中运行良好,但在 Wind
- 在C++,重复申报仍然是一个问题吗?
- "Memory Fragmentation"这仍然是一个问题?
- 缺少类型说明符和另一个问题
- 在浮点精度成为一个问题之前,可以将多少个浮点值加在一起
- 关于使用C++结构的一个问题
- 关于骰子概率计算的一个C++问题
- 我想知道我将如何实现 + 运算符重载.我已经从我上一个问题中计算出 += 运算符重载
- 组合理论的一个问题
- 我有一个问题,创建了C 中阻塞队列的向量
- CreateFileWindows XP和7中存在一个问题
- 我是编码新手,我面临一个问题
- 在添加新记录和访问记录时有一个问题
- 专用纯虚拟模板函数(未定义引用)的另一个问题
- 在C++中,这个Eigen::张量的声明是安全的,还是有缺陷的?我应该为它提交一个问题吗
- 我如何让我的部分代码循环并重复一个问题,直到答案是有效的输入C++
- 我的程序停止工作,因为检测到一个问题