2012-02-09 13 views
12

Estoy extremadamente confundido acerca de la administración de recursos en C++/CLI. Pensé que tenía un identificador (sin juego de palabras), pero tropecé con la clase auto_gcroot<T> mientras miraba los archivos de encabezado, lo que llevó a una búsqueda en Google, luego a la mejor parte de la documentación de lectura diurna y ahora a la confusión. Así que pensé que recurriría a la comunidad.Confusión en la administración de recursos de C++/CLI

Mis preguntas se refieren a la diferencia entre la semántica auto_handle/stack y auto_gcroot/gcroot.

  1. auto_handle: Tengo entendido que esto limpiará un objeto administrado creado en una función administrada. Mi confusión es que no se supone que el recolector de basura haga eso por nosotros. ¿No era ese el objetivo del código administrado? Para ser más específicos:

    //Everything that follows is managed code 
    void WillThisLeak(void) 
    { 
        String ^str = gcnew String ^(); 
        //Did I just leak memory? Or will GC clean this up? what if an exception is thrown? 
    } 
    
    void NotGoingToLeak(void) 
    { 
        String ^str = gcnew String^(); 
        delete str; 
        //Guaranteed not to leak, but is this necessary? 
    } 
    
    void AlsoNotGoingToLeak(void) 
    { 
        auto_handle<String ^> str = gcnew String^(); 
        //Also Guaranteed not to leak, but is this necessary? 
    } 
    
    void DidntEvenKnowICouldDoThisUntilToday(void) 
    { 
        String str(); 
        //Also Guaranteed not to leak, but is this necessary? 
    } 
    

    Ahora bien, esto tendría sentido para mí si se trataba de un reemplazo para el C# usando la palabra clave, y sólo se recomienda para su uso con tipos de recursos intensivos como mapa de bits, pero esto no es mencionado en cualquier parte en la documentación tan im ive miedo sido fugas de memoria todo este tiempo

  2. auto_gcroot

¿Puedo pasarlo como argumento a una función nativa? ¿Qué pasará en la copia?

void function(void) 
    { 
     auto_gcroot<Bitmap ^> bmp = //load bitmap from somewhere 
     manipulateBmp(bmp); 
     pictureBox.Image = bmp; //Is my Bitmap now disposed of by auto_gcroot? 
    } 

    #pragma unmanaged 

    void maipulateBmp(auto_gcroot<Bitmap ^> bmp) 
    { 
     //Do stuff to bmp 
     //destructor for bmp is now called right? does this call dispose? 
    } 

¿Habría funcionado esto si hubiera usado un gcroot?

Además, ¿cuál es la ventaja de tener auto_handle y auto_gcroot? Parece que hacen cosas similares.

Debo estar malentendiendo algo para que esto tenga tan poco sentido, por lo que una buena explicación sería genial. También cualquier guía con respecto al uso apropiado de estos tipos, lugares donde puedo ir para aprender esto, y cualquier otra buena práctica/lugar en que pueda encontrarlos sería muy apreciado.

muchas gracias, Max

+0

nunca uso la mayor parte de las formas aquí: Siempre uso referencias de objetos gestionados y yo siempre dejo que el GC a limpiar para mi. A veces uso 'gcroot', pero rara vez (cuando quiero, por ejemplo, para envolver cierres .NET/delegados en objetos de función C++ y me aseguro de mantener un identificador mientras lo necesito). –

+0

Es un intento bastante erróneo de llevar auto_ptr <> al mundo administrado. Tan tonto como la biblioteca STL/CLR. Lo mejor que puedes hacer es olvidarte de ellos. –

Respuesta

17
  1. Recuerde delete llamada de objeto gestionado es como llamar Desechar en C#. Así que tienes razón, ese auto_handle te permite hacer lo que harías con la declaración using en C#. Asegura que se llame al delete al final del alcance. Entonces, no, no está filtrando la memoria administrada si no usa auto_handle (el recolector de basura se encarga de eso), simplemente no está llamando a Dispose. no hay necesidad de usar auto_handle si los tipos con los que maneja no implementan IDisposable.

  2. gcroot se utiliza cuando desea mantener un tipo administrado dentro de una clase nativa. No puede simplemente declarar un tipo administrado directamente en un tipo nativo usando el símbolo hat ^. Debe usar un gcroot. Esta es una "raíz recolectada de basura". Entonces, mientras el gcroot (un objeto nativo) vive, el recolector de basura no puede recolectar este objeto. Cuando se destruye el gcroot, suelta la referencia y el recolector de basura puede recoger el objeto (suponiendo que no tenga otras referencias). Declaras un gcroot autónomo en un método como el que acabas de hacer: solo usa la sintaxis hat ^ siempre que puedas.

Entonces, ¿cuándo usaría auto_gcroot?Se usaría cuando necesite conservar un tipo gestionado dentro de una clase nativa Y ese tipo gestionado implementa IDisposable. En la destrucción de auto_gcroot, hará 2 cosas: invocar eliminar en el tipo administrado (piense en esto como una llamada a Dispose - no se libera memoria) y libere la referencia (para que el tipo pueda ser recolectado como basura).

Espero que ayude!

Algunas referencias:

http://msdn.microsoft.com/en-us/library/aa730837(v=vs.80).aspx

http://msdn.microsoft.com/en-us/library/481fa11f(v=vs.80).aspx

http://www.codeproject.com/Articles/14520/C-CLI-Library-classes-for-interop-scenarios

+1

¡Finalmente alguien que tiene sentido! –

Cuestiones relacionadas