这些对象的引用是在堆栈上还是在堆上? [英] Are these objects's references on the Stack or on the Heap?

查看:52
本文介绍了这些对象的引用是在堆栈上还是在堆上?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果有人能告诉我我是否理解它,我将不胜感激:

I would really appreciate if someone could tell me whether I understand it well:

class X
{
   A a1=new A(); // reference on the stack, object value on the heap
   a1.VarA=5;    // on the stack - value type
   A a2=a1;      // reference on the stack, object value on the heap
   a2.VarA=10;   // on the stack - value type         
}

此外,a1a2 引用都在堆栈上,而它们的对象"值在堆上.但是 VarA 变量呢,它还是纯值类型?

Also both a1 and a2 references are on the stack, while their "object" values are on the heap. But what about VarA variable, its still pure value type?

class A
{
   int VarA;
}

推荐答案

您问的是关于实现细节的问题,所以答案将取决于特定的实现.让我们考虑一个实际编译的程序版本:

You are asking questions about implementation details, so the answer will depend upon the particular implementation. Let's consider a version of your program that actually compiles:

class A { public int VarA; }
class X
{
    static void Main(string[] args)
    {
        A a1 = new A();
        a1.VarA = 5;
        A a2 = a1;
        a2.VarA = 10;
    }
}

这是在调试模式下运行 C# 4.0 的 Microsoft CLR 4.0 上发生的事情.

here's what happens on Microsoft's CLR 4.0, running C# 4.0, in Debug mode.

此时栈帧指针已经被复制到寄存器ebp中:

At this point the stack frame pointer has been copied into register ebp:

这里我们为新对象分配堆内存.

Here we allocate heap memory for the new object.

A a1 = new A();
mov         ecx,382518h 
call        FFE6FD30 

这会返回对 eax 中堆对象的引用.我们将引用存储在堆栈槽 ebp-48 中,这是一个不与任何名称关联的临时槽.请记住,a1 尚未初始化.

That returns a reference to a heap object in eax. We store the reference in stack slot ebp-48, which is a temporary slot not associated with any name. Remember, a1 has not been initialized yet.

mov         dword ptr [ebp-48h],eax 

现在我们获取刚刚存储在堆栈中的引用并将其复制到 ecx 中,该引用将用于指向 ctor 调用的this"指针.

Now we take that reference we just stored on the stack and copy it into ecx, which will be used for the "this" pointer to the call to the ctor.

mov         ecx,dword ptr [ebp-48h] 

现在我们调用 ctor.

Now we call the ctor.

call        FFE8A518 

现在我们将临时堆栈槽中存储的引用再次复制到寄存器 eax 中.

Now we copy the reference stored in the temporary stack slot into register eax again.

mov         eax,dword ptr [ebp-48h] 

现在我们将 eax 中的引用复制到堆栈槽 ebp-40 中,即 a1.

And now we copy the reference in eax into stack slot ebp-40, which is a1.

mov         dword ptr [ebp-40h],eax 

现在我们必须将 a1 取出到 eax 中:

Now we must fetch a1 into eax:

a1.VarA = 5;
mov         eax,dword ptr [ebp-40h] 

记住,eax 现在是 a1 引用的事物的堆分配数据的地址.那个东西的 VarA 字段是对象的四个字节,所以我们将 5 存储到其中:

Remember, eax is now the address of the heap-allocated data for the thing referenced by a1. The VarA field of that thing is four bytes into the object, so we store 5 into that:

mov         dword ptr [eax+4],5 

现在我们将 a1 的堆栈槽中的引用复制到 eax 中,然后将其复制到 a2 的堆栈槽中,即 ebp-44.

Now we make a copy of the reference in the stack slot for a1 into eax, and then copy that into the stack slot for a2, which is ebp-44.

A a2 = a1;
mov         eax,dword ptr [ebp-40h] 
mov         dword ptr [ebp-44h],eax 

现在正如你所期望的那样,我们将 a2 放入 eax,然后将引用四个字节放入 VarA 中:

And now as you'd expect again we get a2 into eax and then deference the reference four bytes in to write 0x0A into the VarA:

a2.VarA = 10;
mov         eax,dword ptr [ebp-44h] 
mov         dword ptr [eax+4],0Ah

所以你的问题的答案是对对象的引用存储在堆栈中的三个位置:ebp-44、ebp-48 和 ebp-40.它们存储在 eax 和 ecx 的寄存器中.对象的内存(包括其字段)存储在托管堆中.这一切都在 Microsoft 的 CLR v4.0 的调试版本中的 x86 上.如果你想知道在其他一些配置中东西是如何存储在堆栈、堆和寄存器上的,它可能完全不同.引用可以全部存储在堆中,也可以全部存储在寄存器中;可能根本没有堆栈.这完全取决于 jit 编译器的作者如何决定实现 IL 语义.

So the answer to your question is that references to the object are stored in the stack in three places: ebp-44, ebp-48 and ebp-40. They are stored in registers in eax and ecx. The memory of the object, including its field, is stored on the managed heap. This is all on x86 in the debug build, of Microsoft's CLR v4.0. If you want to know how stuff is stored on the stack, heap and registers in some other configuration, it could be completely different. References could all be stored on the heap, or all in registers; there might be no stack at all. It totally depends on how the authors of the jit compiler decided to implement the IL semantics.

这篇关于这些对象的引用是在堆栈上还是在堆上?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆