C++ 如何实现内存堆

C++ 如何实现内存堆,c++,c,memory,heap,allocation,C++,C,Memory,Heap,Allocation,我不确定标题的措辞,但问题是: 我听说过程序员在程序开始时分配一大块连续内存,然后根据需要进行处理。这与每次需要内存时都直接进入操作系统形成对比。 我听说这会更快,因为它可以避免不断向操作系统请求连续内存块的成本 我相信JVM就是这样做的,维护自己的内存部分,然后从中分配对象 我的问题是,如何真正实现这一点?在程序开始时分配足够大的内存块以满足其需要。然后,您必须重写new和/或malloc、delete和/或free以将内存从/返回到该缓冲区 在实现这种解决方案时,您需要编写自己的分配器(从块

我不确定标题的措辞,但问题是:

我听说过程序员在程序开始时分配一大块连续内存,然后根据需要进行处理。这与每次需要内存时都直接进入操作系统形成对比。 我听说这会更快,因为它可以避免不断向操作系统请求连续内存块的成本

我相信JVM就是这样做的,维护自己的内存部分,然后从中分配对象


我的问题是,如何真正实现这一点?

在程序开始时分配足够大的内存块以满足其需要。然后,您必须重写new和/或malloc、delete和/或free以将内存从/返回到该缓冲区

在实现这种解决方案时,您需要编写自己的分配器(从块中获取源代码),最终可能会使用多个分配器,这就是您首先分配内存池的原因


默认内存分配器是一个很好的全能分配器,但不是所有分配需求的最佳分配器。例如,如果您知道您将为特定大小分配大量对象,则可以定义分配固定大小缓冲区并预先分配多个以获得一定效率的分配器。

< P>大多数C和C++编译器已经提供堆内存管理器作为标准库的一部分,因此,您根本不需要做任何事情来避免每个请求都影响操作系统

如果您想提高性能,有许多改进的分配器,您可以简单地链接并使用它们。e、 例如,在一个现在被删除的答案中提到了哪些wheaties(实际上很好——wheaties,你为什么要删除它?)

如果您想编写自己的堆管理器作为学习练习,以下是它需要做的基本事情:

  • 从操作系统请求一大块内存
  • 保留空闲块的链接列表
  • 当收到分配请求时:
    • 在列表中搜索一个块,该块足够大,可以容纳所请求的大小,还可以存储一些簿记变量
    • 为当前请求分割足够大的块,将剩余的块放回空闲列表中
    • 如果没有足够大的块,请返回操作系统并请求另一个大块
  • 当解除分配请求传入时
    • 阅读标题以了解大小
    • 将新释放的块添加到空闲列表中
    • 或者,查看紧跟其后的内存是否也列在空闲列表中,并将两个相邻的块合并成一个更大的块(称为合并堆)

    • 这是经典的分配器,也是非多线程使用的最佳分配器之一:

      你可以从阅读它的设计说明中学到很多东西。文章中的
      malloc.c
      链接已损坏;现在可以在网站上找到它

      话虽如此,除非您的程序有真正不寻常的分配模式,否则编写自己的分配器或使用自定义分配器可能是一个非常糟糕的主意。特别是如果您试图更换系统
      malloc
      ,您可能会遇到来自不同库(或标准库函数)的各种错误和兼容性问题,从而链接到“错误版本的
      malloc

      如果您发现自己只需要为一些特定的任务分配专门的资源,那么这可以在不替换
      malloc
      的情况下完成。我建议在GNU
      obstack
      和对象池中查找固定大小的对象。这些涵盖了专业分配可能具有实际用途的大多数情况

    • 是的,stdlib堆和操作系统堆/虚拟内存都非常麻烦。 操作系统调用非常慢,stdlib速度更快,但仍有一些“不必要的” 锁定和检查,并为分配的块增加大量开销 (即除了分配的内存外,还有一些内存用于管理)
    • 在许多情况下,完全可以避免动态分配, 通过使用静态结构代替。例如,有时定义64k更好(更安全等) unicode文件名的静态缓冲区,然后定义指针/std:string并动态 分配它
    • 当程序必须分配相同结构的许多实例时,其 分配大内存块并将实例存储在那里的速度要快得多 (顺序或使用自由节点的链表)-C++有一个“放置新”,
    • 在许多情况下,在处理不同大小的对象时,可能的大小集 实际上是非常有限的(如4+2*(1..256)),因此可以使用 像[3]这样的几个水池不需要收集垃圾、填补空隙等
    • 通常情况下,特定任务的自定义分配器比单个分配器快得多 来自标准库,甚至比优化速度更快,但实现过于通用
    • 现代CPU/OS支持“大页面”,这可以显著提高内存 显式处理大型块时的访问速度-请参阅

    • IBMdeveloperWorks有一篇关于内存管理的好文章,其中包含大量参考资料部分供进一步阅读:

      维基百科也有一些很好的信息:,。

      你说的“进入操作系统”是什么意思?堆完全在用户模式下实现,除非需要分配更多的页面,否则每次堆分配都不需要系统调用。或者你在想一些不同的东西吗?问题“我如何实现内存管理器”很好,但是你必须确保你真的需要它。如果你这样做是为了训练或只是为了好玩-好的。如果你确实知道内存分配是程序中的一个瓶颈,你应该首先考虑重新设计你的程序,以便它分配更大的块。只有在完成这项工作后,才应该使用自己的内存管理器。Ou