我有一个从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结构列表完成的内存分配处理。上面的代码现在给出了正确的值。
答案 0 :(得分:0)
按现状,托管代码不会导致内存损坏。
但是,除非您明确地对它进行管理,否则根本不会释放非托管内存。
“传统” API通常使用两种方式来处理此问题:
它们在调用时接受一个指针(通常与缓冲区大小信息一起),并将其数据存储在该指针指向的存储区中。在这种情况下,它们不会像使用malloc()
那样分配内存,并且调用方负责提供缓冲区和管理内存。如果缓冲区不够大,则被调用方应返回错误。大多数Win32 API都以这种方式工作(文件访问等)。
它们提供另一个调用以释放内存。在这种情况下,malloc()
和free()
都在您的外部代码中,并且被管理端不会主动管理内存,但是当不再使用指针时,它必须通知外部代码。注意,COM确实使用了相关的引用计数方法。当计数器达到0时,对象被释放。