Marshal.FreeHGlobal() 如何工作?
我有一个基于 C# 的 UI,它使用基于 C++ 的 DLL。我的要求是将一大块内存从 C# 传递到 DLL。 DLL 将写入此内存缓冲区并将其传回 C#。我用过 IntPtr &全局内存函数可以做到这一点。一切正常。
问题是,如何验证 Marshal.FreeHGlobal() 是否已清理内存?我正在使用大块内存,通常以 MB 为单位。所以我想确保内存立即被清理。
I have a C# based UI which uses C++ based DLL. My requirement was to pass a big chunk of memory from C# to DLL. DLL will write into this memory buffer and pass it back to C#. I have used IntPtr & global memory functions to do this. Everything works fine.
The question is, How to verify if the Marshal.FreeHGlobal() has cleaned the memory? I am using big chunk of memory, usually in terms of MBs. So I want to make sure that the memory is cleaned instantly.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您将有效句柄传递给
Marshal.FreeHGlobal
,它将被释放。但由于该方法不返回值,因此您无法确定它是否已被清理。如果您对是否向
FreeHGlobal
传递了正确的内容有一些疑问,那么我建议您的代码可能没有应有的干净。但如果您确实想确定,那么您可以调用LocalFree
Windows API 函数,并将您本来要传递给FreeHGlobal
的句柄传递给它:不过,我建议,如果您这样做,则调用
LocalAlloc
来分配内存,而不是调用Marshal.AllocHGlobal
,因为 .NET 的未来版本有可能(尽管可能不太可能)可以使用LocalAlloc
以外的其他内容来分配非托管内存。如果发生这种情况,那么依赖于LocalFree
的代码将会崩溃。If you pass a valid handle to
Marshal.FreeHGlobal
, it will be freed. But since the method doesn't return a value, you can't say for sure whether it was cleaned up.If you have some doubt as to whether you're passing the right thing to
FreeHGlobal
, then I suggest that your code probably isn't as clean as it should be. But if you really want to make sure, then you could call theLocalFree
Windows API function, passing it the handle that you would have passed toFreeHGlobal
:I would suggest, however, that if you do this, that you call
LocalAlloc
to allocate the memory rather than callingMarshal.AllocHGlobal
, as it's possible (although probably unlikely) that future versions of .NET could use something other thanLocalAlloc
to allocate unmanaged memory. If that happened, then your code that depends onLocalFree
would break.您也可以在托管内存中分配该数组,然后创建一个 GCHandle 以允许从非托管内存访问它。
例如,这里我调用 <代码>PowerReadACValue; Win32 API 函数接受一个
LPBYTE
缓冲区(相当于BYTE*
)。首先,我用“空指针”(IntPtr.Zero)调用它,这样它就会告诉我需要多大的缓冲区(这会输出到 bufferSize 中)。然后我分配缓冲区,并通过 GCHandle 的 AddrOfPinnedObject 传入指针。
或者,我可以使用
Marshal.AllocHGlobal
分配缓冲区,它也会返回一个IntPtr
,然后使用Marshal.FreeGlobal
释放它,但在这种情况下,我需要使用托管代码中的数组中的数据。如果我只是将数组指针传递给另一个非托管函数而不从托管代码中触及它,这将是一个更好的方法(当 GCHandle 处于活动状态时,内存被锁定在内存中,这会影响垃圾收集器)。You can probably also allocate the array in managed memory, and then create a
GCHandle
to allow it to be accessed from unmanaged memory.For example, here I call
PowerReadACValue
; the Win32 API function takes in anLPBYTE
buffer (which equates toBYTE*
).First I call it with a "null pointer" (IntPtr.Zero), so that it will tell me what size buffer I need (this gets output into bufferSize). Then I allocate the buffer, and pass in the pointer via
GCHandle
'sAddrOfPinnedObject
.Alternatively, I could have allocated the buffer with
Marshal.AllocHGlobal
, which also returns me anIntPtr
, and then afterwards free it withMarshal.FreeGlobal
, but in this case I need to use the data in the array from managed code. If I were simply going to pass the array pointer to another unmanaged function without ever touching it from managed code, this would be a better way to go (while the GCHandle is active, the memory is locked into place in memory which affects the garbage collector).