class A
{
public int m_a;
}
void fun(ref int a)
{
...
}
fun(ref new A().m_a);
在 fun 中,“ref int a”如何防止对象 (new A()) 在从 fun 返回之前被回收?
<example 0>
using System;
class A
{
public int m_a;
~A()
{
Console.WriteLine("~A()");
}
}
class Program
{
static void fun(ref int a)
{
Console.WriteLine("Begin<<<<<<<<<<<<<<");
a++;
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("End>>>>>>>>>>>>>>>>>");
}
static void Main(string[] args)
{
fun(ref new A().m_a);
Console.WriteLine("Over");
}
}
output:
Begin<<<<<<<<<<<<<<
~A()
End>>>>>>>>>>>>>>>>>
Over
<example 1>
using System;
class A
{
public int m_a;
~A()
{
Console.WriteLine("~A()");
}
}
class Program
{
static void fun(ref int a)
{
Console.WriteLine("Begin<<<<<<<<<<<<<<");
a++;
GC.Collect();
GC.WaitForPendingFinalizers();
//add a code
a++;
Console.WriteLine("End>>>>>>>>>>>>>>>>>");
}
static void Main(string[] args)
{
fun(ref new A().m_a);
Console.WriteLine("Over");
}
}
output:
Begin<<<<<<<<<<<<<<
End>>>>>>>>>>>>>>>>>
Over
~A()
请在 VS 中通过 Release模式构建。 我查看ASM代码,只加了两行:
a++;
0000002f mov eax,dword ptr [ebp-4]
00000032 inc dword ptr [eax]
两个例子之间的其他部分是相同的。 GC 如何确保变量 a 在机器码中不再有用?
最佳答案
这取决于 a
在 fun
中的使用方式。 GC 能够确定任何给定对象是否有根。在这种情况下,a
是 A
实例中字段 m_a
的别名,并且该对象被认为是 Root过的。但是,如果 JIT 编译器确定 a
未在 fun
的其余部分中使用,则从该点开始在方法中,A
的实例将不再有根并且有资格进行垃圾收集。
一些例子:
void fun(ref int a)
{
// forgot to use a. our object is already eligible for GC!
for(int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
}
void fun2(ref int a)
{
for(int i = 0; i < 10; i++)
{
Console.WriteLine(a);
}
// GC has to wait until a is no longer in use. now our object is eligible for GC.
}
void fun3(ref int a)
{
// can't gc yet. a is still being used.
int b = a;
// b has a copy of the value in a so now our object is eligible for GC.
for(int i = 0; i < 10; i++)
{
Console.WriteLine(b);
}
}
更新:
我不是这在 clr 中如何实现的专家,但我的理解是使用 ref 会导致指向字段 m_a
的托管指针被传递到 fun
。 GC 运行时,根据静态中对堆对象的引用、所有线程的调用堆栈和寄存器来确定根。我在这里猜测,但也许指向字段 m_a
的托管指针存储了对容器对象的引用。或者 GC 可以确定给定托管指针所在的对象。无论哪种方式,该对象都被标记为根自该托管引用。
关于c# - "ref int m_a"如何让包含m a的对象不被GC回收?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11306047/