C++ 关于内存池的问题

C++ 关于内存池的问题,c++,memory-management,fragmentation,memory-pool,C++,Memory Management,Fragmentation,Memory Pool,我需要一些关于内存池的概念和实现的澄清 在维基上,它说 也称为固定大小的块分配, 因为这些实现由于变量的存在而遭受碎片化 块大小,则不可能在实时系统中使用它们 由于性能原因 “可变块大小导致碎片”是如何发生的?固定规模分配如何解决这一问题?这个维基描述听起来有点误导我。我认为固定大小的分配或可变大小的分配并不能避免碎片化。在内存池上下文中,通过为特定应用程序设计特定的内存分配器来避免碎片,或者通过限制使用预期的内存块来减少碎片 此外,通过几个实现示例,例如,在我看来,要使用内存池,开发人员必须非

我需要一些关于内存池的概念和实现的澄清

在维基上,它说

也称为固定大小的块分配, 因为这些实现由于变量的存在而遭受碎片化 块大小,则不可能在实时系统中使用它们 由于性能原因

“可变块大小导致碎片”是如何发生的?固定规模分配如何解决这一问题?这个维基描述听起来有点误导我。我认为固定大小的分配或可变大小的分配并不能避免碎片化。在内存池上下文中,通过为特定应用程序设计特定的内存分配器来避免碎片,或者通过限制使用预期的内存块来减少碎片

此外,通过几个实现示例,例如,在我看来,要使用内存池,开发人员必须非常了解数据类型,然后将数据剪切、拆分或组织到链接内存块(如果数据接近链表)或层次链接块(如果数据组织得更层次,如文件)中。此外,开发人员似乎必须事先预测他需要多少内存

我可以想象这对一组原始数据很有效。什么是C++非原始数据类,其中内存模型不是那么明显?即使对于原始数据,开发人员是否应该考虑数据类型对齐?

C++和C++有好的内存池库吗?p>


谢谢你的评论

可变块大小确实会导致碎片。请看我附上的图片:

图()显示了a、B和C分配内存块、可变大小的块的情况

在某个时刻,B释放了它所有的内存块,突然你就有了碎片。例如,如果C需要分配一大块内存,这仍然可以放入可用内存中,它就不能这样做,因为可用内存被分成两块

现在,如果您考虑每个内存块大小相同的情况,显然不会出现这种情况

当然,内存池也有自己的缺点,正如您自己所指出的。所以你不应该认为记忆池是一根神奇的魔杖。它是有成本的,在特定情况下(即内存有限的嵌入式系统、实时限制等)支付它是有意义的

<>对于C++中哪个内存池是好的,我认为它取决于。我在操作系统提供的VxWorks下使用了一个;从某种意义上说,当一个好的内存池与操作系统紧密集成时,它是有效的。我想,实际上每个RTO都提供了一个内存池的实现

如果您正在寻找通用内存池实现,请参阅

编辑:

从您上次的评论中,我觉得您可能认为内存池是碎片问题的“解决方案”。不幸的是,情况并非如此。如果你愿意,碎片化是熵在内存级别的表现,也就是说,它是不可避免的。另一方面,内存池是一种管理内存的方法,可以有效地减少碎片化的影响(正如我所说的,正如维基百科所提到的,主要是在实时系统等特定系统上)。这会带来成本,因为内存池的效率可能低于“正常”内存分配技术,因为您具有最小的块大小。换句话说,熵在伪装下再现

此外,还有许多参数会影响内存池系统的效率,如块大小、块分配策略,或者您是只有一个内存池,还是有多个具有不同块大小、不同生存期或不同策略的内存池


内存管理确实是一个复杂的问题,内存池只是一种技术,与其他技术一样,它可以提高其他技术的性能,并降低自身的成本。

固定大小和可变大小的内存池都具有碎片化的特点,即在使用过的内存池之间会有一些空闲内存块

对于可变大小,这可能会导致问题,因为可能没有足够大的空闲块来满足特定的请求大小


另一方面,对于固定大小的池,这不是问题,因为只能请求预定义大小的一部分。如果有可用空间,则保证其足够大,可以容纳一部分的(倍数)。

如果使用硬实时系统,则可能需要提前知道可以在允许的最大时间内分配内存。这可以通过固定大小的内存池来“解决”

我曾经在一个军事系统上工作过,我们必须计算系统可能使用的每种大小的内存块的最大可能数量。然后,这些数字被加到一个总数中,系统被配置为具有那个数量的内存

价格贵得离谱,但为国防工作



当您有几个固定大小的池时,您可以得到一个辅助碎片,其中您的池没有块,即使其他池中有足够的空间。您如何共享它?

对于内存池,操作可能是这样的:

  • 存储一个全局变量,该变量是可用对象的列表(最初为空)
  • 要获取新对象,请尝试从可用对象的全局列表中返回一个对象。如果没有,则调用操作符new在堆上分配一个新对象。分配速度非常快,这对于当前可能在内存分配上花费大量CPU时间的某些应用程序来说非常重要
  • 要释放对象,只需将其添加到可用对象的全局列表中即可。您可以对全局列表中允许的项目数设置上限;如果达到上限,则对象将被释放,而不是返回列表。cap可防止出现大规模内存泄漏
  • 注意