2011-12-01 12 views
7

Estoy leyendo sobre el recolector de basura C# y cómo el CLR construye gráficos de objetos. Las referencias capítulo raíces diferentes que podrían ser activa para el objeto:C# Recolección de basura Active Roots

• Las referencias a objetos globales (aunque estos no están permitidos en C#, CIL código hace la asignación de permisos de objetos globales)
• Las referencias a cualquier objetos estáticos/campos estáticos
• referencias a objetos locales dentro de la base de código de una aplicación
• Referencias para oponerse parámetros pasados ​​ en un método
• Las referencias a objetos a la espera de ser fina lized (que se describe más adelante en este capítulo)
• Cualquier registro de la CPU que hace referencia a un objeto

Me preguntaba si alguien podría dar ejemplos de estas raíces en código?

Gracias

Respuesta

7

Supongamos que ejecute el siguiente programa:

class Program 
{ 
    static Class1 foo = new Class1(); 

    static void Main(string[] args) 
    { 
     Class2 bar = new Class2(); 

     Class3 baz = new Class3(); 
     baz = null; 

     Debugger.Break(); 

     bar.Run(); 
    } 
} 

Cuando el programa se rompe en el depurador, hay más de 3 objetos que no son aptos para reciclaje debido a las siguientes referencias:

  • un objeto Class1 referenciado por el campo estático foo
  • un objeto string[] referencia el parámetro args
  • cero o más string objetos referenciados por el objeto string[] referenciado por args
  • un objeto Class2 referenciado por la variable local bar

El objeto Class3 es elegible para la basura recopilación y es posible que ya se haya recopilado o esté esperando su finalización.

Las referencias a objetos globales no están permitidas en C#. Las referencias en los registros de la CPU son un detalle de implementación de la máquina virtual.

+3

En este punto 'bar' puede ser elegible para la recopilación en modo de lanzamiento ya que no se hace referencia después del salto. –

+0

Brian es correcto, 'bar' solo se mantendría con vida en * modo de depuración * seguro hasta el final del método Main, que es solo para la conveniencia de la depuración, en modo de liberación se puede recopilar' bar'. – BrokenGlass

+0

Creo que si se está ejecutando en DEBUG, los objetos estarán siempre seguros hasta que la función finalice de todos modos. Aunque creo que estás en lo correcto con el código optimizado. –

1
class Test 
    { 
     static object ImARoot = new object(); //static objects/static fields 

     void foo(object paramRoot) // parameters I'm a root to but only when in foo 
     { 
      object ImARoot2 = new object(); //local objects but only when I'm in foo. 

      //I'm a root after foo ends but only because GC.SuppressFinalize is not called called (typically in Dispose) 
      SomethingWithAFinalizer finalizedRoot = new SomethingWithAFinalizer(); 


     } 
    } 

Si alguna vez quiere averiguar lo que un objeto tiene sus raíces a en un momento dado puede utilizar SOS (en Visual Studio 2005 o posterior, o en WinDbg) y utilizar el comando gcroot!.

Cuestiones relacionadas