日期:2014-05-18  浏览次数:20771 次

垃圾收集问题——是不是bug
static tc gto;

public class tc
{
public int a=99;

~tc()
{
a=-1; //set breakpoint 1
gto=this;
}
}

private void button1_Click(object sender,EventArgs e)
{
tc to=new tc();
GC.Collect();
GC.WaitForPendingFinalizers();
return; // set breakpoint 2
}

two problems:
click button once,it seem the ~tc() not execute at all.and it will excute at the second time clicking.why?
the second clicking,breakpoint 2, "gto" and "to", gto.a=-1,while to.a=99,why?

------解决方案--------------------
1,在调试时,Visual Studio提供了显示即时值的功能,比如让你的breakpoint 2的地方,能够检查tc的值。
要检查tc的值,这就要求tc不能被垃圾回收,为此Visual Studio调试器插入了特殊代码以保证tc在离开button1_Click()以前不会被回收。

2,Release版就不同了。你把例子用Release编译运行,就会发现,同Debug相反,~tc()在第一次GC.Collect时就被调用了。

3,你的第二个疑问,则这样解释:第二次点击button1_Click的时候,调试器不再需要保留第一个tc实例,于是调用了tc的finalizer()。
设置a=-1,并用gto保存了第一个tc的实例。第二个tc实例则没有被尝试回收(见第一点解释),它的a当然还是99。

4,在finalizer()中把自己赋值给gto,叫做复活。但由于已经调用过一次finalizer()了,以后回收被复活的实例时,
将不会再次调用它的finalizer(),除非在finalizer中显示地调用了GC.ReRegisterForFinalize(this)。