为什么数组分配后的堆如此之大

时间:2011-07-21 21:27:14

标签: c++ arrays memory heap

我有一个非常基本的应用程序,归结为以下代码:

char* gBigArray[200][200][200];
unsigned int Initialise(){  
    for(int ta=0;ta<200;ta++)
        for(int tb=0;tb<200;tb++)
            for(int tc=0;tc<200;tc++)
                gBigArray[ta][tb][tc]=new char;
    return sizeof(gBigArray);
}

该函数返回预期值32000000字节,大约30MB,但在Windows任务管理器中(并且授予它不是100%准确)给出内存(私有工作集)值大约157MB。我已经通过SysInternals将应用程序加载到VMMap中,并具有以下值:

我不确定Image意味着什么(在Type下面列出),尽管它的价值与我所期待的无关。真正为我抛出的东西是Heap值,这是明显巨大的尺寸来源。

我不明白为什么会这样?根据{{​​3}},如果我已经正确理解它,gBigArray将被放置在数据或bss段中 - 但是我猜测每个元素都是未初始化的指针,它将被放置在bss段中。那么为什么堆值会比所要求的更大呢?

8 个答案:

答案 0 :(得分:4)

如果你知道内存分配器是如何工作的,那听起来并不傻。它们跟踪分配的块,因此存在一个存储大小的字段以及指向下一个块的指针,甚至可能是一些填充。有些编译器会在调试版本中的已分配区域周围放置保护空间,因此如果您在分配区域之外或之前编写,程序可以在尝试释放分配的空间时在运行时检测到它。

答案 1 :(得分:2)

您一次分配一个字符。每个分配通常有一个空间开销

在一个大块(或至少在几个块)中分配内存

答案 2 :(得分:1)

不要忘记char* gBigArray[200][200][200];为每个字大小的200*200*200=8000000指针分配空间。这是32位系统上的32 MB。

为另外8MB添加另一个8000000 char。由于你是逐个分配它们,它可能无法在每个项目的一个字节上分配它们,因此它们可能也会采用每个项目的字大小,从而产生另一个32MB(32位系统)。

其余的可能是开销,这也很重要,因为C ++系统必须记住用new分配的数组包含delete []的数量。

答案 3 :(得分:1)

Owww!如果面对该代码,我的嵌入式系统会翻身并死掉。每个分配都有相关的额外信息,并且间隔为固定大小,或通过链表类型对象进行管理。在我的系统上,1个char将成为小型对象分配器中的64字节分配,这样管理将处于O(1)时间。但是在其他系统中,这可能会很容易地破坏你的内存,使后续的新的和删除运行速度非常慢O(n)其中n是它跟踪的事物的数量,并且随着时间的推移随着时间的推移随着每个char变为至少32字节的分配,并放在内存中的各种小型空洞中,从而推动你的分配堆远远超出你的预期。

如果您需要使用贴图新指针或其他指针技巧,请执行单个大型分配并将3D数组映射到其上。

答案 4 :(得分:0)

一次分配1个字符可能更贵。每个分配都有元数据标题,因此字符的1个字节小于标题元数据,因此您可以通过执行一次大的分配(如果可能)来节省空间,这样可以减轻每个具有自己元数据的单独分配的开销。

答案 5 :(得分:0)

也许这是记忆大步的问题?值之间有多大的差距?

答案 6 :(得分:0)

30 MB用于指针。其余的是您使用new调用分配的存储,指针指向。允许编译器出于各种原因分配多个字节,比如在字边界上对齐,或者在以后需要的时候给出一些增长的空间。如果您想要8 MB的字符,请将*gBigArray的声明中删除。

答案 7 :(得分:0)

从上述帖子编辑到社区维基帖

正如下面的答案所说,这里的问题是我创建一个新的char 200 ^ 3次,虽然每个char只有1个字节,但是堆上的每个对象都有开销。似乎为所有字符创建了一个char数组,将内存降低到更可信的水平:

char* gBigArray[200][200][200];
char* gCharBlock=new char[200*200*200];
unsigned int Initialise(){  
    unsigned int mIndex=0;
    for(int ta=0;ta<200;ta++)
        for(int tb=0;tb<200;tb++)
            for(int tc=0;tc<200;tc++)
                gBigArray[ta][tb][tc]=&gCharBlock[mIndex++];
    return sizeof(gBigArray);
}