如何解决Marshal.PtrToStructure是否指向指向本机C ++堆的指针明智?
我有一个使用PInvoke在C#和C ++之间封送数据的应用程序。该应用程序是本机C ++应用程序,可在内部使用C#部分启动CLR。
在某些时候,我必须将数据从C ++封送至C#,为此我正在使用Marshal.PtrToStructure
。 C ++部分基本上是这样的:
struct X {};
auto xPtr = new X; // somewhere in the application
callCSharp(xPtr); // somewhere else
和C#部分如下:
public void callCSharp(IntPtr xPtr)
{
var x = Marshal.PtrToStructure<X>(xPtr);
}
此代码可在我的Windows 10计算机上使用,但是我不确定是否会在此代码上遇到麻烦。生命周期管理都是在C ++中完成的,因此我不必在C#端分配或释放任何东西。但是我不确定CLR是否总是可以访问本机堆。 xPtr
是使用new
分配的,因此位于C ++应用程序的本机堆上。 Marshal.PtrToStructure<X>(xPtr)
然后尝试在该位置读取内存,但我不知道这是否会导致问题。
我已经读过this,这表明C ++应用程序和CLR都使用相同的堆(即GetProcessHeap
),因此这似乎支持了我对Windows 10的发现。与其他操作系统版本不同。
我的示例代码是否理智?这里有陷阱吗?这段代码可以在Windows 7、8和10中运行吗?
解决方法
是的,只要C / C ++代码不释放内存,那是完全合理和安全的。请注意,此处不一定总是(或希望)使用Marshal
;根据{{1}}是什么,您也可以 以其他方式执行此操作,包括:
-
<X>
(将unsafe
投射到void*
) -
X*
(将Unsafe.AsRef<X>(...)
转换为void*
) -
ref X
(从new Span<X>(...)
中创建一定数量的X
的跨度;该跨度就像一个矢量,但与任意内存对话)
所有这些都是零拷贝方法,这意味着您的C#代码随后直接与完全相同的内存空间而不是本地快照进行通信;但是如果您将指针(托管或未托管)取消引用到非引用本地中,则它将进行复制。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。