在C#中,将多少内存分配用于将指针保存到引用的对象?

时间:2012-09-04 12:34:13

标签: c# memory-management

据我所知,在32位机器上,指针占用4个字节(32位)。但是,当我在我的应用程序上运行CLRProfiler时,令我惊讶的是,它显示分配的内存为32个字节,仅用于保存一个接口指针。

Allocated memory for Reference types

从上面的图片可以看出,377910个对象消耗了12 MB,这意味着每个对象32个字节。 我在这里错过了什么吗?

3 个答案:

答案 0 :(得分:0)

引用(而不是指针)存储了其他内容,例如C#'lock'关键字的Monitor

答案 1 :(得分:0)

每个对象的开销。此外,您必须考虑CLR不时填充。见Getting the size of a field in bytes with C#

同样,List会在内部保留更多内存,因为它当前使用。

答案 2 :(得分:0)

尝试增加细节以查看它是否包括引用的实际对象的大小。

相比之下,请尝试以下程序:

class MemTest
{
    private static object[] TakeUpSpace = new object[1024 * 1024];
    public static void Main(string[] args)
    {
        var arr = TakeUpSpace;//make sure it's instantiated.
        Console.ReadKey(true);//keep running so we can profile.
    }
}

在32位机器上进行分析显示一个4MB大小的阵列 - 4 * 1024 * 1024,但没有引用实际对象。

但是这个:

class MemTest
{
    private static object[] TakeUpSpace = new object[1024];
    public static void Main(string[] args)
    {
        var arr = TakeUpSpace;//make sure it's instantiated.
        for(var i = 0; i != 1024; ++i)
            arr[i] = new object();
        Console.ReadKey(true);//keep running so we can profile.
    }
}

显示数组为16KB。 object[]本身是1024 * 4 = 4KB,但每个对象至少有3 *指针大小(字段大小最小为一个指针大小,加上每个对象有两个指针大小的标题)

要求解释标题。

每个.NET对象显然都包含为其定义的字段。如果没有字段,或者字段小于引用的大小,那么它至少会占用那么多。

每个.NET对象都包含一个同步块,其中包含有关是否保留锁定的信息,以及用于编组的其他一些信息。

每个.NET对象都包含一个类型句柄,我们可以从中找出它的类型,虚拟成员的实现以及其他与类型相关的信息。

因此,当你有一个实际的对象 - 而不是一个空引用时,你可以保证为该对象占用至少12字节的内存,同时还有4个用于引用它的内容(当然可以有更多内存)而不是一个引用同一个对象)。如果对象有更多的字段或更大的字段,你可能会占用更多的字段,而且经常是。