什么时候对象可以在C#中进行垃圾回收? [英] When EXACTLY is an object eligible for garbage collection in C#?

查看:116
本文介绍了什么时候对象可以在C#中进行垃圾回收?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我在这里了解了基础知识-当对象不再可由根访问时(即来自堆栈框架中局部变量的静态引用或静态引用),该对象就有资格进行垃圾回收

So I know the basics here - an object is eligible for garbage collection when it's no longer reachable by a root (i.e. a strong reference either from a local variable in a stack frame or a static reference)

我要解决的潜在问题是,即使从局部变量中引用了一个对象,也可能在不再引用该变量的函数中的任何点将其垃圾回收.首先-似乎C#的现有实现不执行此操作-2.0和4.0似乎都保持本地引用处于活动状态",直到堆栈框架被破坏为止.但是-我还想编写代码,如果在以后的CLR版本中对垃圾回收进行了优化时,它仍然很健壮.

The question I have is about this potential optimization where, even if an object is referenced from a local variable, it may be garbage collected at any point in a function where the variable is no longer referenced. First - it appears that existing implementations of C# don't do this - both 2.0 and 4.0 seem to keep local references "live" until the stack frame is destroyed. But - I'd also like to write code that is still robust if and when garbage collection is optimized in later versions of the CLR.

所以-事不宜迟,这是一些代码插图:

So - without further ado, here's some code illustration:

class Foo 
{
  ...
}
class Program
{
    public static void fxn1(int blah) 
    {
      ...
    }
    public static void fxn2(Foo foo)
    {
      ...
    }
    public static int ToInt(Foo foo)
    {
      ...
    }
    public static void Main()
    {
      ...
      Foo foo = new Foo();
      fxn2(foo); // I THINK foo may not be GC'ed until fxn2 returns...
        // I THINK foo may be GC'ed here, even though CLR2.0 and CLR4.0 don't...
        //  (experiment shows CLR 2.0 and 4.0 leave foo "live" until Main returns)
      fxn2(new Foo()); // I THINK the argument can't be GC'ed until fxn2 returns...
        // I KNOW that even CLR2.0 and CLR4.0 will GC the argument after the return...
      fxn1( ToInt(new Foo()) ); // I KNOW that new Foo is GC'able even within fxn1...
    }
}

因此,最终,现有CLR的规则似乎是: 1.在函数调用的持续时间内,任何对象都是活动的",对于该对象而言,它是直接参数 2.如果某个对象被未重新分配的本地堆栈变量引用,则该对象在函数调用期间是活动的". (即使函数末尾的多个指令可能未引用堆栈变量)

So ultimately, the rules for existing CLR's seem to be: 1. any object is "live" for the duration of a function call for which it is an immediate argument 2. any object is "live" for the duration of a function call if it is referenced by a local stack variable that is not reassigned. (even if the stack variable may not be referenced for several instructions at the end of the function)

但是-C#显然保留修改(2)的权利,以使对象一直存在,直到在函数中最终使用引用为止.

However - apparently C# reserves the right to modify (2) so that an object is "live" up until the final use of a reference within a function.

这是否意味着:

Foo foo = new Foo();
Foo foo2 = new Foo();
fxn2(foo); // foo is NOT GC'able until fxn1 returns?
   // foo IS GC'able from here on? (b/c no further uses of local "foo"?)
fxn2(foo2); // foo2 is NOT GC'able within fxn2 ?
fxn1(ToInt(foo2)); // foo2 IS GC'able within fxn1 ? (existing CLR does not GC foo2)

ECMA规范中是否有任何内容详细说明了垃圾回收资格?

Is there anything in the ECMA spec which deals w/ garbage collection eligibility in detail?

推荐答案

@ M.Babcock-感谢您提供ECMA规范的链接! 8.4实际上太笼统了,但是我要寻找的答案是在10.9中-与Java相同-当某个变量无法再由任何可能的将来代码路径引用时,则认为该变量可以进行垃圾回收-这意味着尽管现有的clr实现似乎将局部变量生存期的范围限制在堆栈中,但不能保证第三方或将来的实现会做到这一点.

@M.Babcock - Thank you for the link to the ECMA spec! 8.4 was actually too general, but the answer I was looking for was in 10.9 - and is identical to Java - when a variable can be no longer referenced by any possible future code path, then it is considered eligible for garbage collection - which means that although the existing clr implementation seems to scope local variable lifetime to the stack, there's no guarantee that third party or future implementations will do so.

这篇关于什么时候对象可以在C#中进行垃圾回收?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆