显式大小的可用内存

B_o*_*old 6 c c++ memory-management

我在寻找malloc/ free主流操作系统般的API,允许我既分配和重新分配过程中指定一个明确的大小。我希望从中获得的收益是,当程序中已分配大小时,运行时可以在记账上花费更少的内存。

在例如Windows上,我只找到了free(),_aligned_free()和_freea(),它们都没有第二个参数作为大小。

Use*_*ess 3

我正在主流操作系统中寻找类似于 malloc/free 的 API,这些 API 允许我在分配和取消分配期间指定明确的大小。

我不知道有什么。

我希望由此获得的是,当程序中分配的大小已经可用时,运行时可能会在簿记上花费更少的内存。

这个想法当然可行,但有一些缺点:

  1. 您必须在分配大小由调用者跟踪的对象和分配器仍需要自行记录的对象之间划分分配区域。

    这增加了复杂性并可能增加内存碎片。

  2. 您必须准确分配程序请求的大小。

    也就是说,普通分配器可能决定为 64 字节请求返回 96 字节块,因为它刚刚被释放,在缓存上很热,并且分割和重新合并小于 64 字节的块被认为是不值得的。

    一般来说,您的分配器不能这样做(它仅限于向上舍入到下一个对齐的块大小)。


当然,有很多专门的分配器可以明确地管理这些权衡。

当通用分配器不太适合您的分配模式时,使用或编写这些是完全正常的事情。但是,它们通常不是由语言或操作系统提供的,因为它们不是通用的。它们由图书馆(或您自己)提供。

例子:

  1. 您分配并释放了许多具有先前已知的固定大小的对象。

    为它们编写一个对象池分配器。它不需要跟踪分配大小,因为它总是相同的(通常是模板参数)。您也不需要在代码中显式跟踪它,因为它是由类型隐含的。

  2. 具有相同生命周期的普通对象的可变大小分配(例如,大量的字符缓冲区)。

    编写一个竞技场分配器。它不需要跟踪单个分配大小,因为您重置整个分配器而不是释放和重新分配单个对象。您永远不会显式删除分配对象,因为它们无论如何都是微不足道的。

注意。如果您选择使用new/delete重载来集成您的分配器(并且认为它将受益于显式大小参数),您绝对可以使用 Maxim 指出的那些,但需要注意以下几点:

...如果提供了用户定义的替换,则将调用[显式大小重载]而不是[默认重载],除非未指定在删除不完整类型的对象以及非类和平凡的数组时调用[哪个] -可破坏的类类型。