17 votes

Confusion dans la gestion des ressources en C++/CLI

Je suis extrêmement confus en ce qui concerne la gestion des ressources en C++/CLI. Je pensais avoir la main (sans jeu de mots) sur le sujet, mais je suis tombé sur l'article suivant auto_gcroot<T> J'ai donc fait une recherche sur Google, puis j'ai passé une bonne partie de la journée à lire la documentation, et maintenant je suis confus. J'ai donc décidé de me tourner vers la communauté.

Mes questions portent sur la différence entre la sémantique auto_handle/stack et auto_gcroot/gcroot.

  1. auto_handle : Si j'ai bien compris, cela permet de nettoyer un objet géré créé dans une fonction gérée. Ma confusion vient du fait que le ramasse-miettes n'est pas censé le faire à notre place ? N'était-ce pas le but du code géré ? Pour être plus précis :

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

    Cela me paraîtrait logique s'il s'agissait d'un remplacement du mot-clé using en C#, et s'il n'était recommandé que pour les types gourmands en ressources comme Bitmap, mais cela n'est mentionné nulle part dans la documentation, et j'ai donc peur d'avoir des fuites de mémoire depuis tout ce temps.

  2. auto_gcroot

Puis-je le passer comme argument à une fonction native ? Que se passera-t-il lors de la copie ?

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

Cela aurait-il fonctionné si j'avais utilisé un gcroot à la place ?

De plus, quel est l'avantage d'avoir auto_handle et auto_gcroot ? Il semble qu'ils fassent des choses similaires.

Je dois avoir mal compris quelque chose pour que cela ait si peu de sens, une bonne explication serait donc la bienvenue. De même, tout conseil concernant l'utilisation correcte de ces types, les endroits où je peux aller pour apprendre ces choses, et toute autre bonne pratique/endroit où je peux les trouver serait grandement apprécié.

Merci beaucoup, Max

28voto

Matt Smith Points 6843
  1. Se souvenir delete appelée sur un objet géré s'apparente à l'appel de Dispose en C#. Vous avez donc raison, auto_handle vous permet de faire ce que vous feriez avec la fonction using en C#. Elle garantit que delete est appelé à la fin du champ d'application. Donc, non, vous ne fuyez pas la mémoire gérée si vous n'utilisez pas auto_handle (le ramasse-miettes s'en occupe), vous n'appelez pas Dispose. Il n'est pas nécessaire d'utiliser auto_handle si les types auxquels vous avez affaire n'implémentent pas IDisposable.

  2. gcroot est utilisé lorsque vous souhaitez conserver un type géré à l'intérieur d'une classe native. Vous ne pouvez pas déclarer un type géré directement dans un type natif en utilisant la méthode hat ^ symbole. Vous devez utiliser un gcroot. Il s'agit d'un "garbage collected Root". Ainsi, tant que le gcroot (un objet natif) vit, le ramasse-miettes ne peut pas collecter cet objet. Lorsque le gcroot est détruit, il abandonne la référence et le ramasse-miettes est libre de collecter l'objet (en supposant qu'il n'a pas d'autres références). Vous déclarez une gcroot autonome dans une méthode comme vous l'avez fait ci-dessus - il suffit d'utiliser le chapeau ^ chaque fois que vous le pouvez.

Quand utiliseriez-vous auto_gcroot ? Il est utilisé lorsque vous devez conserver un type géré dans une classe native ET que ce type géré implémente IDisposable. Lors de la destruction de l'auto_gcroot, il fera 2 choses : appeler delete sur le type géré (pensez à cela comme un appel Dispose - aucune mémoire n'est libérée) et libérer la référence (de sorte que le type puisse être ramassé par les poubelles).

J'espère que cela vous aidera !

Quelques références :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X