Подтвердить что ты не робот

С++/CLI Управление ресурсами

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

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

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

    Теперь это имело бы смысл для меня, если бы это заменило ключевое слово С#, и оно было рекомендовано только для использования с такими ресурсоемкими типами, как Bitmap, но это не упоминается нигде в документах, поэтому я боялся утечки память все это время

  • 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? Похоже, они делают подобные вещи.

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

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

4b9b3361

Ответ 1

  • Помните, что delete вызываемый управляемый объект сродни вызову Dispose в С#. Итак, вы правы, что auto_handle позволяет делать то, что вы делаете с оператором using в С#. Это гарантирует, что delete вызывается в конце области. Итак, нет, вы не пропускаете управляемую память, если вы не используете auto_handle (сборщик мусора позаботится об этом), вы просто не вызываете Dispose. нет необходимости использовать auto_handle, если типы, с которыми вы работаете, не реализуют IDisposable.

  • gcroot используется, когда вы хотите удерживать управляемый тип внутри собственного класса. Вы не можете просто объявить manged-тип непосредственно в родном типе, используя символ шляпы ^. Вы должны использовать 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