首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >幕后的对象:“.NET”存储了什么?

幕后的对象:“.NET”存储了什么?
EN

Stack Overflow用户
提问于 2011-04-06 11:06:08
回答 2查看 671关注 0票数 8

一个朴素的类型系统会将对象存储为指向其类型的指针(它包含许多有用的信息,如vtable、对象大小等)。然后是它的数据。如果.Net具有这样的类型系统,则object在32位系统上将占用4个字节,而在64位系统上将占用8个字节。

We can see that it doesn't。对象开销是两个指针大小,另外,还有一个指针大小的“最小”大小。

那么object在幕后到底存储了什么呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-04-06 11:17:21

是的,看起来就是这样。“类型句柄”,又名“方法表指针”位于偏移量0处,对象数据位于偏移量4处。在偏移量-4处有一个额外的字段,名为“syncblock”。它存在的原因是,当对象空间未被使用时,它还会参与垃圾收集堆,这是一个需要两个指针的空闲块的双向链表。不要浪费,同步块有几种用途,比如存储锁状态,存储哈希码,当需要存储太多内容时存储指向显式同步块的指针。

最小的对象是一个装箱的字节,4+4+1=9个字节。但是GC堆的分配粒度是4字节,因此您将得到4,12字节的下一个倍数。

这在Visual Studio中的调试器中非常明显。您可以在this answer中找到提示。

票数 7
EN

Stack Overflow用户

发布于 2011-04-06 11:08:38

(这一切都来自Microsoft Shared Source CLI;它有CLR的源代码。)

如果你看一下clr\src\vm\object.h,你会看到:

代码语言:javascript
运行
复制
// The generational GC requires that every object be at least 12 bytes in size.
#define MIN_OBJECT_SIZE     (2*sizeof(BYTE*) + sizeof(ObjHeader))

这是非常不言而喻的。此外,在clr\src\vm\gcscan.cpp中,您可以看到如下语句

代码语言:javascript
运行
复制
_ASSERTE(g_pObjectClass->GetBaseSize() == MIN_OBJECT_SIZE);

代码语言:javascript
运行
复制
_ASSERTE(totalSize < totalSize + MIN_OBJECT_SIZE);

我想这就解释了为什么你会看到意想不到的物体大小。:)

更新:

@Hans在sync块上有一个很好的观点;我只想指出一个微妙之处,在object.h中再次记录下来

代码语言:javascript
运行
复制
/* Object
 *
 * This is the underlying base on which objects are built. The MethodTable
 * pointer and the sync block index live here. The sync block index is actually
 * at a negative offset to the instance. See syncblk.h for details.
 */

class Object
{
    protected:
        MethodTable*    m_pMethTab;
    //No other fields shown here!
};

请注意这一部分:

对于实例,同步块索引实际上处于负偏移量(

)。

显然,sync块实际上并不遵循方法表(正如Hans提到的那样),但它位于方法表之前--因此它不是对象的“正常”部分(因为没有更好的词)。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5561008

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档