C++为变量分配异常大的amout内存

Nav*_*een 11 c++ memory integer memory-management function-pointers

我最近知道一个整数从内存中占用4个字节.

首先运行此代码,并测量内存使用情况:

int main()
{
   int *pointer;
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 花了144KB.

然后我修改了代码以分配1000个整数变量.

int main()
{
   int *pointer;

   for (int n=0; n < 1000; n++)
     { 
       pointer = new int ; 
     }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 然后花了(168-144 =)24KB,
    但假设1000个整数占用(4bytes x 1000 =)3.9KB.

然后我决定制作262,144个整数变量,它们应该消耗1MB的内存.

int main()
{
   int *pointer;

   for (int n=0; n < 262144; n++)
     { 
       pointer = new int ; 
     }
}
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是,现在需要8MB

在此输入图像描述

内存使用量,指数增长各自的整数.
为什么会这样?

我在Kubuntu 13.04(amd64)
请给我一点解释.谢谢!

注意:sizeof(integer)退货4

Ker*_* SB 14

单独分配的动态对象的内存不需要是连续的.事实上,由于对对齐要求new char[N](即在对齐alignof(std::maxalign_t),通常是16),标准内存分配器可能只是从来就不愿返回任何东西,但 16字节对齐的内存.因此每个int分配实际上消耗(至少)16个字节.(分配器可能需要进一步的内存来进行内部簿记.)

道德当然是你应该用来理解std::vector<int>(1000000)一百万个动态整数.

  • @Naveen因为`int`需要4个字节的存储空间.但是使用`new`,你不仅得到`int`所需的内存,而且还得到分配开销.在某处,需要存储已分配内存的大小,以便实现知道例如`delete []`多少.所以你得到簿记+对齐开销_per allocation_.如果你一次性分配`N``int`s,你只需要一次开销. (4认同)
  • @Barmar:我不相信实际情况就是如此.OP确实像两个实验,并声称这证明了一些东西. (3认同)
  • @Naveen:不要混淆*memory*和*objects*.这就像混淆面粉和苹果派.你需要一个人来获得另一个,但是当他们被扔进你的脸时他们会感觉非常不同. (3认同)
  • @Naveen因为`int`s数组中`int`s'之间的距离是4. (2认同)

Pix*_*ist 10

公共分配器中的非优化分配会带来一些开销.你可以想到两个"块":一个INFO和一个STORAGE块.信息块很可能就在您的STORAGE块前面.

因此,如果你分配你将在你的记忆中有这样的东西:

        Memory that is actually accessible
        vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
--------------------------------------------
|  INFO |  STORAGE                         |
--------------------------------------------
^^^^^^^^^
Some informations on the size of the "STORAGE" chunk etc.
Run Code Online (Sandbox Code Playgroud)

另外,块将沿着某个粒度对齐(在int的情况下有点像16个字节).

我将在MSVC12上写下它的外观,因为我现在可以对它进行测试.

我们来看看我们的记忆吧.箭头表示16字节边界.

在int分配的情况下的内存布局;  每个块代表4个字节

如果分配一个4字节整数,则在某个16字节边界(第二个边界之后的橙色方块)将获得4个字节的内存.在该块之前的16个字节(蓝色的)被占用以存储附加信息.(我会在这里跳过诸如endianess之类的内容,但请记住,这会影响这种布局.)如果你在分配的内存前读取这个16字节块的前四个字节,你会发现分配的数量字节.

如果你现在分配第二个4字节整数(绿色框),它的位置将至少是16字节边界的2倍,因为INFO块(黄色/红色)必须适合它前面,这不是右下边界的情况.红色块再次是包含字节数的块.

您可以很容易地看到:如果绿色块早先是16个字节,则红色和橙色块会重叠 - 不可能.

你可以自己检查一下.我正在使用MSVC 2012,这对我有用:

char * mem = new char[4096];
cout << "Number of allocated bytes for mem is: " << *(unsigned int*)(mem-16) << endl;
delete [] mem;


double * dmem = new double[4096];
cout << "Number of allocated bytes for dmem is: " << *(unsigned int*)(((char*)dmem)-16) << endl;
delete [] dmem;
Run Code Online (Sandbox Code Playgroud)

版画

Number of allocated bytes for mem is: 4096
Number of allocated bytes for dmem is: 32768
Run Code Online (Sandbox Code Playgroud)

这是完全正确的.因此,在MSVC12的情况下,使用new的存储器分配具有额外的"INFO"块,其大小至少为16字节.