0

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

为引用类型分配的内存

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

4

3 回答 3

0

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

于 2012-09-04T12:47:10.823 回答
0

每个对象都有开销。此外,您还必须考虑 CLR 会不时进行填充。请参阅使用 C# 获取字段的大小(以字节为单位)

此外,列表在内部保留了当前使用的更多内存。

于 2012-09-04T12:58:53.473 回答
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 个字节(当然可以有多个引用到同一个对象)。如果对象具有更多字段或更大的字段,您可能会占用更多,而且通常会如此。

于 2012-09-04T13:09:33.720 回答