从堆中为对象实际分配了多少内存?

时间:2009-06-04 09:15:36

标签: c++ visual-c++ memory memory-management

我有一个程序使用太多内存来分配堆上的大量小对象。所以我想研究一下优化它的方法。该程序使用Visual C ++ 7编译。

有没有办法确定为给定对象实际分配了多少内存?我的意思是当我调用 new 时,堆分配不小于所需的数量。我怎样才能找到确切分配的数量?

6 个答案:

答案 0 :(得分:9)

没有确切的答案,因为一些堆管理器可能会使用不同数量的内存来进行相同大小的顺序分配。此外,(通常)没有直接的方法来测量特定分配所花费的字节数。

您可以通过分配一定数量的相同大小的项目(例如,4096)并注意使用的内存差异来估算此值。将前者除以前者会给你答案。请注意,此值从操作系统更改为操作系统,从操作系统版本更改为操作系统版本,有时应用程序的调试版本可能会启用额外的堆跟踪,从而增加了开销。在某些操作系统上,用户可以更改堆策略(即默认使用一个堆分配器与另一个堆分配器)。示例:Windows和pageheap.exe

仅供参考,Windows 32位上的默认(非LFH)堆占用:

  • sizeof(your_type),向上舍入到DWORD边界,
  • prev / next / size的3个指针
  • 2个安全cookie指针

答案 1 :(得分:4)

您可能希望转向内存池模型(这是之前关于“分配大型池”的答案所描述的内容。因为内存池不需要每次分配的开销,所以它们可以节省大量空间如果一组小对象的生命周期很短(即你分配了一堆小对象然后需要摆脱批次),内存池也要快得多,因为你可以只更新池每个对象。

维基百科有关于该技术的一些信息以及一些实现的链接:

http://en.wikipedia.org/wiki/Memory_pool

您应该能够通过简单的网络搜索找到其他实现。

答案 2 :(得分:3)

并非以平台无关的方式确定。我不记得任何手头的细节(除了操作系统,我很确定你没有使用),但是你的操作系统可能会提供一种方法来测试malloc-ed分配的“大小”,以及新的使用malloc或等价物。因此,您可能能够获得内存分配器所认为的分配大小。这可能包括也可能不包括分配前的任何标题(可能不是,我猜)。

一种选择是分配几百万个小对象,并查看程序使用的内存量。然后分配几百万再看一遍。由于操作系统为RAM(或虚拟地址空间)分配了进程,因此总数通常会以块为单位,但是对于大量对象,这种“舍入错误”的影响通常会趋向于每个对象0个字节。

这应该告诉你你可能想知道什么,这是许多小堆对象的平均内存开销。它将包括内存分配器的任何簿记开销,例如分配之前的标头,或跟踪分配和/或块的外部结构。

答案 3 :(得分:1)

如果你知道你要做很多小的分配并且你担心内存碎片,为什么不分配一个大的缓冲区然后映射到那个呢?如果您正在进行分配/解除分配的批次,您可能会看到一些性能改进。

StackOverflow有some useful posts pertaining to avoiding memory fragmentation,可能会有所帮助。

答案 4 :(得分:1)

在Windows下,您可以使用Heap32FirstHEAPENTRY32结构来确定任何给定堆条目的大小,假设您没有使用自定义堆管理器。还值得指出的是,由于保护字节,分配块的大小在调试中可能比发布版本大。我没有在MSDN中看到Heap64功能,所以我猜他们只是使用Heap32名称。

答案 5 :(得分:0)

[编辑] 这个答案错了​​!我将它作为不该做的一个例子。 sizeof 函数运算符在编译时工作。


你试过了吗?

SomeClass* some_instance = new SomeClass;
printf("Size of SomeClass == %u", sizeof(*some_instance) );

我似乎记得通过传入一个类的实例,你应该得到分配的大小。