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编译器可能会优化某些部分,使其不使用堆栈,而是直接转到寄存器 以方法调用为例:
JIT编译器将尝试将尽可能多的参数放入寄存器中,而不是将它们放入堆栈中。在X86上本地构建的示例显示:object a = new object(), b = new object(), c = new object(); DoSomething(a, b, c);
现在还有更复杂的情况,请考虑数组/对象访问。考虑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.Split()生成一个数组,该数组必须保持对此语句(部分)的可访问性。但是没有指向它的变量或参数,优化器很可能将引用保存在寄存器中string sentence = ... int wordCount = sentence.Split(' ').Length;
所以CPU(地址)寄存器必须被视为根的一部分 你的程序集示例没有多大意义,你需要更好地解释你的问题是什么。
对!如果它一直在那里,为什么我还要记得登记册?是否存在“f”不包含真实引用的阶段?在因此引用只存在于变量中
返回后,但在执行new Foo()
之前,对=
的引用仅存在于寄存器中。如果忽略寄存器,则在Foo
和赋值操作之间发生的GC将过早地对对象进行GC。@RoyiNamir:是的,有些阶段引用仅存在于寄存器中。在上面的示例中,在调用构造函数和将值存储在变量中的指令之间,引用只存在于寄存器中。may:)取决于JIT编译器。在这种情况下,是的new Foo()
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;