Marshal.AllocHGlobal VS Marshal.AllocCoTaskMem,Marshal.SizeOf VS的sizeof() [英] Marshal.AllocHGlobal VS Marshal.AllocCoTaskMem, Marshal.SizeOf VS sizeof()

查看:648
本文介绍了Marshal.AllocHGlobal VS Marshal.AllocCoTaskMem,Marshal.SizeOf VS的sizeof()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下结构:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct WAVEHDR
{
    internal IntPtr lpData;   // pointer to locked data buffer
    internal uint dwBufferLength; // length of data buffer
    internal uint dwBytesRecorded; // used for input only
    internal IntPtr dwUser;   // for client's use
    internal uint dwFlags;   // assorted flags (see defines)
    internal uint dwLoops;   // loop control counter
    internal IntPtr lpNext;  // reserved for driver
    internal IntPtr reserved;  // reserved for driver
}

我需要分配非托管内存来存储上述结构的实例。一个指向这个结构将被传递到waveout的Win32 API函数(waveout的prepareHeader,waveOutWrite,waveOutUn prepareHeader)。

I need to allocate unmanaged memory to store an instance of above struct. A pointer to this struct will be passed to waveOut win32 api functions (waveOutPrepareHeader, waveOutWrite, waveOutUnprepareHeader).

  1. 我应该使用 Marshal.AllocHGlobal() Marshal.AllocCoTaskMem()?有什么区别?
  2. 我应该通过的sizeof(WAVEHDR) Marshal.SizeOf(typeof运算(WAVEHDR))的内存分配方法?有什么区别?
  1. Should I use Marshal.AllocHGlobal() or Marshal.AllocCoTaskMem()? What is the difference?
  2. Should I pass sizeof(WAVEHDR) or Marshal.SizeOf(typeof(WAVEHDR)) to the memory allocation method? What is the difference?

请注意,分配的内存必须被固定。

推荐答案

一个Windows程序总是在非托管内存分配至少两个堆。首先是默认的进程堆,Windows使用时,它需要代表程序分配内存。二是所用的COM结构分配堆。在.NET的P / Invoke编组假设这堆被用于任何非托管code,其函数签名要求取消分配内存。

A Windows program always has at least two heaps in which unmanaged memory is allocated. First is the default process heap, used by Windows when it needs to allocate memory on behalf of the program. The second is a heap used by the COM infrastructure to allocate. The .NET P/Invoke marshaller assumes this heap was used by any unmanaged code whose function signature requires de-allocating memory.

从的AllocHGlobal进程堆分配,AllocCoTaskMem分配从COM堆中。

AllocHGlobal allocates from the process heap, AllocCoTaskMem allocates from the COM heap.

每当你写的非托管互操作code,你应该总是避免的情况下code表示分配非托管内存是不一样的code表示将其释放。这里将是一个很好的机会,错解分配器使用。这是任何code,它与C / C ++程序互操作性展示更是如此。这样的程序有自己的分配器,它使用自己的堆,由CRT在启动时创建的。在其他code去分配这些内存是不可能的,你不能可靠地获得堆句柄。这是P的一个很常见的源/ Invoke的麻烦,特别是因为在XP中的HeapFree()函数和前面默默地忽略请求,这不是分配权堆中空闲内存(泄漏已分配的内存),但是Vista和Win7的崩溃程序有例外。

Whenever you write unmanaged interop code, you should always avoid a situation where code that allocates unmanaged memory is not the same as the code that frees it. There would be a good chance that the wrong de-allocator is used. This is especially true for any code that interops with a C/C++ program. Such programs have their own allocator that uses its own heap, created by the CRT at startup. De-allocating such memory in other code is impossible, you can't reliably get the heap handle. This is a very common source of P/Invoke trouble, especially because the HeapFree() function in XP and earlier silently ignore requests to free memory that wasn't allocated in the right heap (leaking the allocated memory) but Vista and Win7 crash the program with an exception.

没有必要担心这个,你的情况,你使用的是MMSYSTEM API函数是干净的。他们的目的是确保在同一code的分配也将释放。这是一个原因,你必须调用waveIn prepareHeader(),它分配的缓冲区使用相同的code,最终将释放他们。可能与默认进程堆。

No need to worry about this in your case, the mmsystem API functions you are using are clean. They were designed to ensure the same code that allocates also deallocates. This is one reason you have to call waveInPrepareHeader(), it allocates buffers with the same code that ultimately deallocates them. Probably with the default process heap.

您只需要分配WAVEHDR结构。而你是负责释放它,当你用它做。该MMSYSTEM API不为你做,最重要的是,因为他们不能这样做可靠。因此,您可以使用分配器,你只需要确保调用相应的自由的方法。所有的Windows API以这种方式工作。我使用CoTaskMemAlloc来(),但是是不是真的有一个preference。只是,如果我打电话糟糕设计code,这是稍微更有可能使用COM堆。

You only need to allocate the WAVEHDR structure. And you are responsible for releasing it when you're done with it. The mmsystem APIs don't do it for you, most of all because they cannot do so reliably. Accordingly, you can use either allocator, you just need to make sure to call the corresponding free method. All Windows APIs work this way. I use CoTaskMemAlloc() but there really isn't a preference. Just that if I'm calling badly designed code, it is slightly likelier to use the COM heap.

您不应该使用的sizeof()在互操作场景。它返回的值类型的管理规模。可能不是在P之后的同一/调用编组已根据[StructLayout]和[的MarshalAs]指令翻译的结构类型。只有Marshal.SizeOf()为您提供了保证正确的值。

You should never use sizeof() in an interop scenario. It returns the managed size of value type. That might not be the same after the P/Invoke marshaller has translated a structure type according to the [StructLayout] and [MarshalAs] directives. Only Marshal.SizeOf() gives you a guaranteed correct value.

更新:有在VS2012大的变化。现在包括它的C运行时库分配从默认的进程堆而不是用自己的堆。从长远来看,这使得中的AllocHGlobal最有可能的途径取得成功。

UPDATE: there was a big change in VS2012. The C runtime library included with it now allocates from the default process heap instead of using its own heap. Long term, that makes AllocHGlobal the most likely avenue for success.

这篇关于Marshal.AllocHGlobal VS Marshal.AllocCoTaskMem,Marshal.SizeOf VS的sizeof()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆