2012-02-09 17 views
12

Sono estremamente confuso riguardo la gestione delle risorse in C++/CLI. Pensavo di avere un manico (nessun gioco di parole) su di esso, ma mi sono imbattuto nella classe auto_gcroot<T> mentre guardavo attraverso i file di intestazione, che hanno portato a una ricerca su google, quindi la parte migliore della documentazione di lettura del giorno, e ora la confusione. Quindi ho pensato di rivolgermi alla comunità.Confusione gestione risorse C++/CLI

Le mie domande riguardano la differenza tra semantica auto_handle/stack e auto_gcroot/gcroot.

  1. auto_handle: La mia comprensione è che questo pulirà un oggetto gestito creato in una funzione gestita. La mia confusione è che il garbage collector non dovrebbe farlo per noi? Non era questo il punto del codice gestito? Per essere più precisi:

    //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? 
    } 
    

    Ora, questo avrebbe senso per me se fosse una sostituzione per il C# utilizzando parole chiave, ed è stato raccomandato solo per l'uso con i tipi ad alta intensità di risorse, come bitmap, ma questo non è menzionato da nessuna parte nella documentazione così im ive paura stato perdite di memoria per tutto questo tempo ora

  2. auto_gcroot

Posso passarlo come argomento a una funzione nativa? Cosa succederà sulla 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? 
    } 

Questo avrebbe funzionato se avessi usato un gcroot invece?

Inoltre, qual è il vantaggio di avere auto_handle e auto_gcroot? Sembra che facciano cose simili.

Devo essere frainteso qualcosa per cui questo non ha molto senso, quindi una buona spiegazione sarebbe grandiosa. Inoltre, qualsiasi consiglio riguardante l'uso corretto di questi tipi, i luoghi in cui posso andare a imparare queste cose e qualsiasi altra buona pratica/luogo in cui posso trovarli sarebbe molto apprezzato.

grazie mille, Max

+0

non ho mai utilizzare la maggior parte delle forme qui: Io uso sempre i riferimenti per gli oggetti gestiti e ho sempre lasciato che il GC li ripulire per me. A volte uso 'gcroot', ma raramente (quando voglio ad esempio per avvolgere le chiusure/delegati .NET in oggetti funzione C++ e mantenere un handle per tutto il tempo necessario). –

+0

È un tentativo abbastanza pesante di portare auto_ptr <> nel mondo gestito. Sciocco come la libreria STL/CLR. La cosa migliore da fare è dimenticarsene. –

risposta

17
  1. Ricorda delete invitato oggetto gestito è simile a chiamando Dispose in C#. Quindi hai ragione, che auto_handle ti consente di fare ciò che vorresti fare con l'istruzione using in C#. Assicura che delete venga chiamato alla fine dell'ambito. Quindi, no, non stai perdendo la memoria gestita se non usi auto_handle (il garbage collector si prende cura di quello), semplicemente non riesci a chiamare Dispose. non è necessario utilizzare auto_handle se i tipi con cui gestisci non implementano IDisposable.

  2. gcroot viene utilizzato quando si desidera conservare un tipo gestito all'interno di una classe nativa. Non puoi semplicemente dichiarare un tipo gestito in un tipo nativo usando il simbolo cappello ^. Devi usare un gcroot. Questa è una "radice raccolta rifiuti". Quindi, mentre il gcroot (un oggetto nativo) vive, il garbage collector non può raccogliere questo oggetto. Quando il gcroot viene distrutto, lascia andare il riferimento e il garbage collector è libero di raccogliere l'oggetto (supponendo che non abbia altri riferimenti). Dichiari un gcroot indipendente in un metodo come quello che hai fatto sopra - usa la sintassi del cappello ^ ogni volta che puoi.

Quindi quando si utilizzerà auto_gcroot?Esso verrebbe utilizzato quando è necessario conservare un tipo gestito in una classe nativa E che il tipo gestito si implementa con IDisposable. Alla distruzione di auto_gcroot, farà 2 cose: chiama delete sul tipo gestito (pensa a questo come una chiamata di Dispose - non viene liberata memoria) e libera il riferimento (in modo che il tipo possa essere gettato via).

Spero che aiuti!

Alcune referenze:

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 qualcuno che abbia un senso! –

Problemi correlati