为什么不收集未引用的对象

本文关键字:对象 引用 为什么不 | 更新日期: 2023-09-27 18:03:04

程序输出"True"到控制台

分配一个对象,使其为WeakReference,转到out of block作用域,并检查WeakReference. isalive

public static void Main (string[] args)
{
    Test ();
}
static void Test ()
{
    WeakReference wref = null;
    { // block scope
        var obj = new object ();
        wref = new WeakReference (obj);
    }
    // obj is out of scope
    // Console.WriteLine (obj);
    GC.Collect ();
    Console.WriteLine (wref.IsAlive); // => True
}

为什么不收集obj,虽然obj超出了作用域?

程序由Mono 3.12.0编译。

编辑:

对不起,不恰当的例子。

下面的程序也打印True。块范围似乎没有关系。这是在调试模式下尝试的not

    public static void Main (string[] args)
    {
        Test ();
    }
    static void Test ()
    {
        WeakReference wref = null;
        var obj = new object ();
        wref = new WeakReference (obj);
        obj = null;
        GC.Collect ();
        Console.WriteLine (wref.IsAlive); // => True
    }

$ mcs -debug- Program.cs
$ mono Program.exe

为什么不收集未引用的对象

我猜是因为你在调试器中运行。

尝试运行发布版本,并在调试器之外手动运行。

您希望GC是100%确定的,当它不是。

一些可能发生的事情:

  • JIT优化空赋值。
  • 指向实例的指针可以留在临时堆栈位置,或者在寄存器中(您调用函数,传递变量,这将把变量放在某些体系结构的寄存器中)。

GC结束后。收集,添加:

GC.WaitForPendingFinalizers(); 

通过调用这个过程,所有可终结的对象都可以在继续程序之前执行任何必要的清理。它确保你的代码不会调用当前正在销毁的对象上的方法。