Путаница управления ресурсами C ++ / CLI - PullRequest
14 голосов
/ 10 февраля 2012

Я очень запутался в управлении ресурсами в C ++ / CLI.Я думал, что у меня есть дескриптор (без каламбура), но я наткнулся на класс auto_gcroot<T>, просматривая файлы заголовков, что привело к поиску в Google, а затем к лучшему в дневном чтении документации, а теперь и к путанице.Так что я решил обратиться к сообществу.

Мои вопросы касаются разницы между семантикой auto_handle / stack и auto_gcroot / gcroot.

  1. auto_handle: Насколько я понимаю, это приведет к очистке управляемого объекта, созданного вуправляемая функция.Мое замешательство в том, что сборщик мусора не должен делать это для нас?Разве не в этом весь смысл управляемого кода?Чтобы быть более конкретным:

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

    Теперь это будет иметь смысл для меня, если бы оно было заменой ключевого слова C # using, и его рекомендовали использовать только с ресурсоемкими типами, такими как Bitmap, но это не так.упоминается где-нибудь в документации, так что, боюсь, я все это время терял память

  2. auto_gcroot

Могу ли я передать его в качестве аргументародная функция?Что будет на копии?

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

Сработало бы это, если бы вместо этого я использовал gcroot?

Кроме того, в чем преимущество использования auto_handle и auto_gcroot?Похоже, что они делают подобные вещи.

Я, должно быть, что-то неправильно понимаю, чтобы в этом было так мало смысла, так что хорошее объяснение было бы здорово.Также будет очень благодарна за любые рекомендации относительно правильного использования этих типов, мест, куда я могу пойти, чтобы изучить этот материал, и любых других полезных практик / мест, которые я могу найти их.

спасибо большое, Макс

1 Ответ

22 голосов
/ 10 февраля 2012
  1. Помните, delete, вызываемый на управляемом объекте, похож на вызов Dispose в C #.Итак, вы правы, этот auto_handle позволяет вам делать то, что вы делаете с оператором using в C #.Это гарантирует, что delete вызывается в конце области.Итак, нет, вы не теряете управляемую память, если вы не используете auto_handle (сборщик мусора позаботится об этом), вы просто не можете вызвать Dispose.Нет необходимости использовать auto_handle, если типы, с которыми вы работаете, не реализуют IDisposable.

  2. gcroot используется, когда вы хотите сохранить управляемый тип внутри собственного класса.Вы не можете просто объявить управляемый тип непосредственно в нативном типе, используя символ шляпы ^.Вы должны использовать gcroot.Это «корень мусора».Таким образом, пока gcroot (собственный объект) живет, сборщик мусора не может собрать этот объект.Когда gcroot уничтожен, он освобождается от ссылки, и сборщик мусора может свободно собирать объект (при условии, что у него нет других ссылок).Вы объявляете автономный gcroot в методе, который вы сделали выше - просто используйте синтаксис hat ^ всякий раз, когда можете.

Так когда бы вы использовали auto_gcroot?Он будет использоваться, когда вам нужно держаться за управляемый тип внутри собственного класса, а этот управляемый тип реализует IDisposable.При уничтожении auto_gcroot он будет выполнять 2 действия: вызывать delete для управляемого типа (представьте, что это вызов Dispose - память не освобождается) и освобождает ссылку (чтобы тип мог быть собран сборщиком мусора).

Надеюсь, это поможет!

Некоторые ссылки:

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

...