C# 误解的根源?

C# 误解的根源?,c#,.net-4.0,garbage-collection,C#,.net 4.0,Garbage Collection,我知道根是: 静态场 方法参数 地方封地 f-queue,其中还包含指向“即将完成”对象的指针 cpu寄存器寄存器仅临时保存变量值 例如,创建对象并将引用存储在变量中时: Foo f = new Foo(); 发生的是调用构造函数,并返回对对象的引用。在此阶段,引用仅存在于寄存器中。然后寄存器的内容被复制到变量中,因此现在引用同时存在于寄存器和变量中。然后寄存器继续运行并用于其他内容,因此引用只存在于变量中 还要注意的是,不仅仅是寄存器中当前的值才是根。每个线程都有自己的一组寄存器,当线程

我知道根是:

  • 静态场
  • 方法参数
  • 地方封地
  • f-queue,其中还包含指向“即将完成”对象的指针

  • cpu寄存器寄存器仅临时保存变量值

    例如,创建对象并将引用存储在变量中时:

    Foo f = new Foo();
    
    发生的是调用构造函数,并返回对对象的引用。在此阶段,引用仅存在于寄存器中。然后寄存器的内容被复制到变量中,因此现在引用同时存在于寄存器和变量中。然后寄存器继续运行并用于其他内容,因此引用只存在于变量中



    还要注意的是,不仅仅是寄存器中当前的值才是根。每个线程都有自己的一组寄存器,当线程不运行时,这些寄存器会切换到内存,所有这些寄存器值也都是根。

    因为JIT编译器可能会优化某些部分,使其不使用堆栈,而是直接转到寄存器

    以方法调用为例:

    object a = new object(), b = new object(), c = new object();
    DoSomething(a, b, c);
    
    JIT编译器将尝试将尽可能多的参数放入寄存器中,而不是将它们放入堆栈中。在X86上本地构建的示例显示:

    00000082  push        dword ptr [ebp-10h] 
    00000085  mov         ecx,dword ptr [ebp-8] 
    00000088  mov         edx,dword ptr [ebp-0Ch] 
    0000008b  call        dword ptr ds:[00742078h] 
    
    现在还有更复杂的情况,请考虑数组/对象访问。

    考虑

    string sentence = ...
    int wordCount = sentence.Split(' ').Length;
    
    String.Split()生成一个数组,该数组必须保持对此语句(部分)的可访问性。但是没有指向它的变量或参数,优化器很可能将引用保存在寄存器中


    所以CPU(地址)寄存器必须被视为根的一部分

    你的程序集示例没有多大意义,你需要更好地解释你的问题是什么。
    因此引用只存在于变量中
    对!如果它一直在那里,为什么我还要记得登记册?是否存在“f”不包含真实引用的阶段?在
    new Foo()
    返回后,但在执行
    =
    之前,对
    Foo
    的引用仅存在于寄存器中。如果忽略寄存器,则在
    new Foo()
    和赋值操作之间发生的GC将过早地对对象进行GC。@RoyiNamir:是的,有些阶段引用仅存在于寄存器中。在上面的示例中,在调用构造函数和将值存储在变量中的指令之间,引用只存在于寄存器中。may:)取决于JIT编译器。在这种情况下,是的
    00000082  push        dword ptr [ebp-10h] 
    00000085  mov         ecx,dword ptr [ebp-8] 
    00000088  mov         edx,dword ptr [ebp-0Ch] 
    0000008b  call        dword ptr ds:[00742078h] 
    
    string sentence = ...
    int wordCount = sentence.Split(' ').Length;