在C#中从字节数组获取IntPtr是否存在内存泄漏风险的可能性

4

我需要使用外部DLL将数据发送到设备。我在DLL中使用的方法需要一个指向字节数组的指针作为参数。由于我使用的是C#,因此我使用GCHandle.Alloc方法获取内存地址,并将其分配给一个IntPtr实例。然后我将IntPtr作为参数传递。我的担心是代码中可能存在内存泄漏的风险,因为我之前没有在C#中使用过指针和内存分配。当前的代码如下所示:

GCHandle pinned = GCHandle.Alloc(byteArray, GCHAndleType.Pinned);
IntPtr arrayPtr = pinned.AddrOfPinnedObject();

var result = _externalDll.SendInfo(arrayPtr, byteArray.Length);   

pinned.Free();

这是分配和使用IntPtr的正确方法吗?看起来它可以工作,但由于该代码每天需要在生产环境中并发运行约100次,因此最好避免任何主要问题。


3
你可能根本不需要这样做。你能提供外部 DLL 中函数的签名吗?我假设它是 C(或使用 cdecl 的 C++)? - Matthew Watson
这段代码没问题,不会产生内存泄漏。假设SendInfo同步使用arrayPtr且不将其存储以备将来使用,那么逻辑也是正确的。 - Alex F
1
另一种方法是:Marshal.AllocHGlobal + Marshal.Copy + SendInfo + Marshal.FreeHGlobal。这种方式可以避免固定,但会增加复制操作。 - Alex F
很不幸,我并没有签名,只有一些文档(它将其定义为:SendInfo(char* table, int bytes))和一封开发者确认应该是byte[]而不是char的电子邮件。我怀疑Stephen Martin可能是正确的,我应该能够只传递字节数组,然后让运行时处理剩下的部分。谢谢。 - Bonnotbh
1个回答

3
通常情况下,只有在非托管代码将会保留指向您的指针以供稍后使用时,您才需要使用GCHandle
在这里,您似乎只是传递指针,然后立即释放它。如果是这种情况,则根本不应该使用GCHandle。只需将第一个参数设置为byte[]并直接传递byteArray即可。运行时将负责固定数组对象,用于调用期间,并将指向数组第一个元素的指针传递给非托管代码。

这听起来可能会奏效。我只是被函数文档要求提供指针所困扰了。非常感谢! - Bonnotbh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接