从C#代码访问C代码中分配的结构内存

时间:2018-12-28 11:57:44

标签: c memory-leaks c#

我有一个从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);

            }
        }
    }

在上面的代码中,当从C#端访问时,可能会松开对Sampledata结构列表完成的内存分配处理。上面的代码现在给出了正确的值。

1 个答案:

答案 0 :(得分:0)

按现状,托管代码不会导致内存损坏。

但是,除非您明确地对它进行管理,否则根本不会释放非托管内存。

“传统” API通常使用两种方式来处理此问题:

  • 它们在调用时接受一个指针(通常与缓冲区大小信息一起),并将其数据存储在该指针指向的存储区中。在这种情况下,它们不会像使用malloc()那样分配内存,并且调用方负责提供缓冲区和管理内存。如果缓冲区不够大,则被调用方应返回错误。大多数Win32 API都以这种方式工作(文件访问等)。

  • 它们提供另一个调用以释放内存。在这种情况下,malloc()free()都在您的外部代码中,并且被管理端不会主动管理内存,但是当不再使用指针时,它必须通知外部代码。注意,COM确实使用了相关的引用计数方法。当计数器达到0时,对象被释放。