C # вызывает C ++ метод, который возвращает указатель. Объясните управление памятью - PullRequest
1 голос
/ 27 октября 2010

Может ли кто-нибудь объяснить, что именно происходит с точки зрения низкого уровня / управления памятью в строках 2 C # в «Main», следующим образом?

Код C ++ (неуправляемый):

    #define DLLEXPORT extern "C" __declspec(dllexport)

    DLLEXPORT MyClass* MyClass_MyClass()
    {
        return new MyClass();
    }
    DLLEXPORT void MyClass_setName(MyClass* myClass, const char* name)
    { 
        myClass->setName(name);
    }

MyClass::MyClass()
{
    _name.clear();
}
void MyClass::setName(const char* name)
{
    _name.setCString(name, NAME_MAX_BYTES);
}

C # код:

        [DllImport(@"lib.dll")]
        private static extern IntPtr MyClass_MyClass();
        [DllImport(@"lib.dll")]
        public static extern void MyClass_setName(
                    IntPtr myClass,
                    [System.Runtime.InteropServices.InAttribute()]
                    [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
                    string name);

        public static void Main(string[] args)
        {
            var myClass = MyClass_MyClass();
            MyClass_setName(myClass , "Test Name");
        }

В частности, мне интересно, как .NET знает, сколько места выделяется для "myClass"? Надо делать что-то вроде "Marshal.AllocHGlobal (SIZE)" на заднем плане, верно? Что произойдет, если потребуется больше места (я установил имя?)? Кроме того, есть ли риск того, что сборщик мусора будет запущен, переместит память и испортит мой "IntPtr myClass"?

Ответы [ 2 ]

1 голос
/ 27 октября 2010

.NET ничего не знает о типе MyClass, он хранит только указатель на него.Размер указателя всегда известен и фиксирован - 4 байта для 32-битных процессов и 8 байтов для 64-битных процессов.Все выделение памяти и управление ею в данном конкретном случае происходит в неуправляемом коде C ++ здесь:

return new MyClass();

и здесь:

myClass->setName(name);

Решение о том, как распределять / освобождать, зависит от DLL C ++/ управление памятью, код C # будет просто вызывать импортированные функции этой DLL.

Для вашего неуправляемого объекта сбор мусора не будет выполняться, и вам потребуется предоставить дополнительный (неуправляемый) метод для его освобождения, чтобы избежать утечки памяти.

0 голосов
/ 27 октября 2010

Если код c ++ не управляется, .net не выделяет ничего, кроме IntPtr. Он выделяется кодом C ++.

Это означает, что единственная сборка мусора будет выполняться на этом IntPtr. Поскольку это мало, может пройти много времени, прежде чем сборщик мусора решит очистить его.

Это означает, что даже если ваш код C ++ хорошо очищается после самого себя, может пройти много времени, прежде чем он действительно выполнит очистку. Код C ++ может использовать тонну памяти, но он невидим для .net, поэтому он не будет расставлять приоритеты для очистки над «большими» объектами .net.

...