我有一个从 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 结构列表完成的内存分配句柄。因为上面的代码现在给出了正确的值。
最佳答案
按原样,托管代码不应出现内存损坏。
但是,除非您明确执行某些操作,否则非托管内 stub 本不会被释放。
“传统”API 通常使用两种方法来处理此问题:
它们在调用时接受一个指针(通常带有缓冲区大小信息),并将数据存储在指针指向的内存区域中。在这种情况下,它们不会像使用
malloc()
那样分配内存,调用者负责提供缓冲区并管理内存。如果缓冲区不够大,被调用者应该返回错误。大多数 Win32 API 都是这样工作的(文件访问等)。他们提供了另一个调用来释放内存。在这种情况下,
malloc()
和free()
都在您的外部代码中,并且托管端不会主动管理内存,但它必须在何时通知外部代码指针不再使用。请注意,COM 确实使用了引用计数的相关方法;当计数器达到 0 时,对象被释放。
关于c - 从 C# 代码访问 C 代码中分配的结构体内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53959846/