Итак, я знаю основы: объект пригоден для сборки мусора, когда он более недоступен для корня (т. Е. Сильная ссылка либо из локальной переменной в кадре стека, либо из статической ссылки)
У меня есть вопрос об этой потенциальной оптимизации, когда, даже если на объект ссылаются из локальной переменной, он может собирать мусор в любой точке функции, на которую больше не ссылаются переменные.Во-первых - кажется, что существующие реализации C # не делают этого - и 2.0, и 4.0, кажется, поддерживают локальные ссылки «живыми», пока фрейм стека не будет разрушен.Но - я также хотел бы написать код, который по-прежнему устойчив, если и когда сборка мусора будет оптимизирована в более поздних версиях CLR.
Итак, без лишних слов, вот несколько иллюстраций кода:
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. любой объект является «живым» на времявызов функции, если на него ссылается локальная переменная стека, которая не переназначена.(даже если на переменную стека нельзя ссылаться для нескольких инструкций в конце функции)
Тем не менее - очевидно, C # оставляет за собой право изменить (2), чтобы объект был «живым» вплоть до последнегоиспользование ссылки внутри функции.
Это будет означать:
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 что-нибудь, что подробно описывает право на сборку мусора?