DxC*_*xCK 23 .net c# winapi memory-management unmanaged
我有以下结构:
[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
}
Run Code Online (Sandbox Code Playgroud)
我需要分配非托管内存来存储上面结构的实例.指向此结构的指针将传递给waveOut win32 api函数(waveOutPrepareHeader,waveOutWrite,waveOutUnprepareHeader).
Marshal.AllocHGlobal()或Marshal.AllocCoTaskMem()?有什么不同?sizeof(WAVEHDR)还是Marshal.SizeOf(typeof(WAVEHDR))内存分配方法?有什么不同?注意必须固定分配的内存.
Han*_*ant 43
Windows程序始终至少有两个堆,其中分配了非托管内存.首先是Windows在需要代表程序分配内存时使用的默认进程堆.第二个是COM基础结构用于分配的堆..NET P/Invoke marshaller假定任何非托管代码使用此堆,其功能签名需要取消分配内存.
AllocHGlobal从进程堆分配,AllocCoTaskMem从COM堆分配.
无论何时编写非托管互操作代码,都应该始终避免分配非托管内存的代码与释放它的代码不同的情况.使用错误的解除分配器的可能性很大.对于使用C/C++程序进行交互的任何代码尤其如此.这些程序有自己的分配器,它使用自己的堆,由CRT在启动时创建.在其他代码中取消分配这样的内存是不可能的,你无法可靠地获得堆处理.这是P/Invoke问题的一个非常常见的原因,特别是因为XP和更早版本中的HeapFree()函数无声地忽略了释放未在正确堆中分配的内存的请求(泄漏分配的内存)但Vista和Win7崩溃了程序有例外.
在您的情况下无需担心这一点,您使用的mmsystem API函数是干净的.它们旨在确保分配也释放的相同代码.这是你必须调用waveInPrepareHeader()的一个原因,它使用相同的代码分配缓冲区,最终解除分配它们.可能与默认进程堆.
您只需要分配WAVEHDR结构.当你完成它时,你有责任释放它.mmsystem API不适合你,最重要的是因为它们无法可靠地执行此操作.因此,您可以使用任一分配器,您只需要确保调用相应的自由方法.所有Windows API都以这种方式工作.我使用CoTaskMemAlloc(),但确实没有偏好.只是如果我调用设计错误的代码,使用COM堆稍微有点可能.
您绝不应在互操作方案中使用sizeof().它返回值类型的托管大小.在P/Invoke marshaller根据[StructLayout]和[MarshalAs]指令转换结构类型之后,这可能不一样.只有Marshal.SizeOf()为您提供有保证的正确值.
更新:VS2012发生了很大的变化.它包含的C运行时库现在从默认进程堆分配,而不是使用自己的堆.从长远来看,这使得AllocHGlobal成为最有可能取得成功的途径.
| 归档时间: |
|
| 查看次数: |
10062 次 |
| 最近记录: |