可能重复:
Is there any guarantee of alignment of address return by C++'s new operation?
在此程序中,我打印 new 返回的每个地址,用于未签名的字符。然后最后将它们向后删除。
#include "stdafx.h"
#include<stdlib.h>
void func();
int main()
{
int i=10;
while(i-->0)printf("loaded %i \n", (new unsigned char));
getchar();
unsigned char *p=new unsigned char;printf("last pointer loaded %i \n", p);
i=10;
while(i-->0)delete (p-=64);
getchar();
p+=640;
delete p;//nearly forgot to delete this ^^
return 0;
}
输出:
如您所见,每个 new 都会返回64字节对齐的数据。
问题:这个64字节是等于缓存行大小还是只是编译器的东西?
问题:我应该将结构设置为大多数64字节长吗?
问题:当我更改我的cpu,ram,OS或编译器时,这会有所不同吗?
Pentium-m,VC ++ 2010 express,windows-xp
感谢。
答案 0 :(得分:2)
当您考虑在大量分配和解除分配之后发生的情况时,堆管理器的实现选择更有意义。
对malloc()
的调用需要找到一个足够大小的未使用块来分配。
它可能更大(在这种情况下,它可以创建一个带有差异的自由块 - 或者浪费它)。找到最接近块大小的简单策略称为最适合。如果它继续创建新的空闲块,您也可以将其称为最差假。
使用后,最适合的方法会导致大量碎片,这些碎片是由不太可能再次分配的小块引起的,并且搜索空闲块的成本变高。
因此,高性能堆管理器不能像这样工作。相反,它们作为各种固定块大小的池分配器运行。虽然投入一些中间体,但是块的权力为2(例如64,128,256,512...
)范围的方案也可能是有价值的(例如48,96,192...)
。在此方案中,malloc()
和{{1这两个操作都是free()
,分配中的关键部分是最小的 - 可能是每个池 - 这在多线程环境中很重要。
小分配中的内存浪费比碎片,O(1)
alloc \ dealloc复杂性和糟糕的MT性能要小得多。
最小块大小w.r.t.缓存线大小是经典的工程权衡之一,可以肯定的是,微软做了相当多的实验,以O(n)
作为最小值。 FWIW,我很确定你会发现现代CPU的缓存行大小比这更大。