Доступ к структуре памяти, выделенной в коде C из кода C # - PullRequest
0 голосов
/ 28 декабря 2018

У меня есть список структур, выделенных из кода C.Я возвращаю указатель этого списка структуры на код C #.И, наконец, код C # использует этот указатель и помещает его в соответствующий список структур C #.Оба кода C и C # связаны вместе.

Я хотел подтвердить, есть ли вероятность повреждения памяти в этом сценарии или может быть случай, когда мы потеряем указатель на указатель памяти.Когда память, выделенная из кода C, будет уничтожена.

Ниже приведен фрагмент кода.

Образец кода C

 typedef struct sampleData {
    int id;
    int sid;
 } SampleData; 

  SampleData* func(){
    SampleData* pd = (SampleData*) malloc(10 * sizeof(SampleData)) ;
    for(int i=0;i<10;i++){
       pd[i].id=i*10;
       pd[i].sid=i*10;
    }
    return pd;
}

образец кода C #

class Test
    {
    [StructLayout(LayoutKind.Sequential, Pack=1)]
        public struct TestData{

            [MarshalAs(UnmanagedType.I4)]
            public int id;
            [MarshalAs(UnmanagedType.I4)]
            public int sid;
        }

        [DllImport("sample.so", EntryPoint = "func")]
        static extern IntPtr func();

        public void collectSampleData()
        {
            IntPtr idPtr = IntPtr.Zero;
            IntPtr sidPtr = IntPtr.Zero;
            idPtr = func();

            for(int i=0;i<10;i++){

                TestData TestDataObj=new TestData();

                IntPtr currPtr = new IntPtr(idPtr.ToInt64() + ( i * Marshal.SizeOf(typeof(TestData))));

                TestDataObj = (TestData)Marshal.PtrToStructure(currPtr,typeof(TestData));

                Console.WriteLine(TestDataObj.id+" "TestDataObj.sid);

            }
        }
    }

В приведенном выше коде есть возможность потерять дескриптор выделения памяти для списка структуры Sampledata при доступе со стороны C #.Поскольку приведенный выше код на данный момент дает правильные значения.

1 Ответ

0 голосов
/ 28 декабря 2018

Как есть, в управляемом коде не должно быть повреждений памяти.

Однако неуправляемая память вообще не будет освобождена, если вы явно не сделаете с этим что-либо.

"Традиционные API обычно используют два способа решения этой проблемы:

  • Они принимают указатель (обычно вместе с информацией о размере буфера) при вызове и сохраняют свои данные в области памяти, на которую указывает указательк.В этом случае они не выделяют память, как вы делаете с malloc(), и вызывающая сторона отвечает за предоставление буфера и управление памятью.Если буфер недостаточно велик, вызываемый должен вернуть ошибку.Большинство Win32 API работают таким образом (доступ к файлам и т. Д.).

  • Они предоставляют еще один вызов для освобождения памяти.В этом случае malloc() и free() находятся в вашем внешнем коде, и управляемая сторона не активно управляет памятью, но должна уведомить внешний код, когда указатель больше не используется.Обратите внимание, что COM использует связанный подход с подсчетом ссылок;когда счетчик достигает 0, объект освобождается.

...