2016-12-14 111 views
0

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

+0

CLR不会分配每个对象的实例。相反,它会根据需要分配大段,然后用于保存对象。 –

回答

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; 
} 

编译并运行,采用64作为目标平台,产生了以下说明在拆卸观看时:

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和一个short分配了两个字节。

如果我们用更小的数字,如字节或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的内存考虑应该集中在对象创建和生命周期管理上,而不是值类型。

+0

您将这些项目分配为本地变量,因此它们在堆栈上而不在堆上。恕我直言,在堆上,开销很大。另一方面,分配一个数组非常有效,因为只有数组会有一个标题,而不是每个单独的项目。 –

+0

由于.NET数据类型具有定义的长度,所以在32位和64位之间应该没有太大区别。 Int16将始终为16位。 –

+0

它们是一个类的公共字段,以main为实例。他们不在堆栈中,他们生活在堆的对象之内。地址显示了这一点,该对象获得一个64字节长的块。而且正如你所说的,x32和x64之间的区别在于,它不是为64位数据类型分配两个双字,而是使用qwords,并使用其他指令来操纵它们。 – Espen