.NET CLR最小内存分配(32/64位)

时间:2016-12-14 20:28:38

标签: .net garbage-collection clr

我试图找到可以通过CLR在32位和64位系统中分配的最低内存块的底部。在我看来,在32位系统上,它将分配4个字节的块,而在64位上,它将分配8个字节的块。如果为true,那么Int32在64位系统上是否需要8字节的地址空间?

1 个答案:

答案 0 :(得分:1)

如果您查看以下代码:

public class Numbers
{
    public Int16 A = 1;
    public Int32 B = 2;
    public Int64 C = 3;
    public UInt16 D = 4;
    public UInt32 E = 5;
    public UInt64 F = 6;
    public short G = 7;
    public int H = 8;
}

在反汇编视图中查看时,使用x64作为目标平台进行编译和运行会产生以下说明:

7:         public Int16 A = 1;
mov         rcx,qword ptr [rbp+50h]  
mov         word ptr [rcx+24h],1  

 8:         public Int32 B = 2;
mov         rcx,qword ptr [rbp+50h]  
mov         dword ptr [rcx+18h],2  

 9:         public Int64 C = 3;
mov         ecx,3  
movsxd      rcx,ecx  
mov         rax,qword ptr [rbp+50h]  
mov         qword ptr [rax+8],rcx  

10:         public UInt16 D = 4;
mov         rcx,qword ptr [rbp+50h]  
mov         word ptr [rcx+26h],4  

11:         public UInt32 E = 5;
mov         rcx,qword ptr [rbp+50h]  
mov         dword ptr [rcx+1Ch],5  

12:         public UInt64 F = 6;
mov         ecx,6  
movsxd      rcx,ecx  
mov         rax,qword ptr [rbp+50h]  
mov         qword ptr [rax+10h],rcx  

13:         public short G = 7;
mov         rcx,qword ptr [rbp+50h]  
mov         word ptr [rcx+28h],7  

14:         public int H = 8;
mov         rcx,qword ptr [rbp+50h]  
mov         dword ptr [rcx+20h],8  
mov         rcx,qword ptr [rbp+50h]  

从中可以看出它根据数据类型分配了2,4和8个字节。不是这样,它分配处理器的字大小块,在Windows上一个字总是16位,一个双字总是32位,而在x64上你有四个字。

为证明这一点,您可以查看内存中的地址空间以及值的堆叠方式:

![Memory block allocations

现在您必须注意,由于CLR管理的所有内存,这并不总是可预测的行为。正如您从我的示例中看到的,它为Int64和UInt64分配了8个字节,为Int32,UInt32和int分配了4个字节,对于UInt16和短路仅分配了2个字节。

如果我们使用更小的数字,例如byte或bool,就像这样:

public class Numbers
{
    public byte I = 10;
    public bool J = true;
}

我们得到另一个结果:

 7:         public byte I = 10;
mov         rcx,qword ptr [rbp+50h]  
mov         byte ptr [rcx+8],0Ah  

 8:         public bool J = true;
mov         rcx,qword ptr [rbp+50h]  
mov         byte ptr [rcx+9],1  

现在它使用字节,每个只使用1个字节。

Allocation of 2 bytes

对象在64位的块中存在于堆中: Object viewed on the heap

然而,CLR并不总是以这种方式将其组织在内存中。 从堆映射中可以看出,CLR为该对象分配了一个64字节的块,并尝试将所有对象块放在那里。它使用尽可能多的聪明才能这样做。

我尝试了几个不同的版本,并且分配空间依赖于行为,如果CLR分配太少,它将重新分配到其他地方并移动指针,例如地址空间的前8个字节用于保持3,它在前4个字节中有一些与对象相关的数据,因此与其他数据共享8个字节。并且它将继续这样做,直到它需要该空间来保持'C'的值。它的一种方法是看它是否可以将C向上移动以获得占用的空间。

因此,为了回答您的问题,它将分配的最小块将根据应用程序以及CLR如何选择为您的程序组织内存而有所不同。您不应该将您的类型视为内存块,认为它们的大小代表了保存它们的最大/最小值所需的最大内存。

一个好的经验法则是认为它分配了类型所需的最大所需空间,四舍五入到字节,但由于CLR将为您管理所有这些,您实际上并不需要担心它。 .NET上的内存注意事项应该集中在对象创建和生命周期管理上,而不是值类型。