Mic*_*lGG 2 c c# pinvoke winapi
我在Windows上看过,malloc与CoTaskMemAlloc不同,后者与AllocHGlobal不同.对于C#使用者来说,这可能意味着如果我有一个返回malloc指针的C函数,我需要在其上调用free.如果IP/Invoke并指定字符串返回类型,则CLR应该调用CoTaskMemFree并且应该在malloc指针上失败.
但是,我无法在实践中看到这一点.我创建了一个DLL,它只返回一个malloc'd char*和P/Invoked它作为一个字符串.没有内存泄漏.实际上,无论我尝试什么,我都无法让事情失败.我调用malloc,GlobalHAlloc,CoTaskMemAlloc,然后使用任何免费的实现,只是工作.没有内存泄漏.重新使用相同的内存空间.
我怎么能强迫它失败?或者这是那些应该是"实现定义"的东西,但实际上只是单向工作?
这是在VS2015 Update 2,Windows 8.1上.
这当然不习惯工作.但事情一直在变化.在VS2012中更改了 C运行时库,它不再创建自己的堆.对于VS2015,此代码在C:\ Program Files(x86)\ Windows Kits\10\Source\10.0.10240.0\ucrt\heap\heap_handle.cpp中是相关的:
// Initializes the heap. This function must be called during CRT startup, and
// must be called before any user code that might use the heap is executed.
extern "C" bool __cdecl __acrt_initialize_heap()
{
__acrt_heap = GetProcessHeap();
if (__acrt_heap == nullptr)
return false;
return true;
}
Run Code Online (Sandbox Code Playgroud)
注意对GetProcessHeap()的调用,它返回Marshal.AllocHGlobal()分配的相同堆.所以是的,当您使用Marshal.FreeHGlobal()取消分配时,您不会从调试堆中获得异常,也不会泄漏.
CoTaskMemAlloc()大致相同.单步进入功能,我看到:
7638D1E1 mov esi,dword ptr [g_CMalloc (76485EE0h)]
7638D1E7 push dword ptr [ebp+8]
7638D1EA mov esi,dword ptr [esi+0Ch]
7638D1ED cmp esi,offset CRetailMalloc_Alloc (763732C0h)
7638D1F3 jne CoTaskMemAlloc+44h (7638D214h)
7638D1F5 push 0
7638D1F7 push dword ptr [g_hHeap (76485E68h)]
7638D1FD call dword ptr [__imp__HeapAlloc@12 (76488228h)]
Run Code Online (Sandbox Code Playgroud)
注意g_hHeap变量的用法.我看到它与GetProcessHeap()返回的值相同.因此,使用任何释放函数释放都可以正常工作.
请注意,我从Windows 10获得此功能,Windows的旧版本不会以相同的方式运行.并注意CRetailMalloc_Alloc,一个不太令人愉快的随机函数,具有不可预测的用法.
虽然这当然是有帮助的,但程序失败的方式要少得多,但在测试应用程序时实际上并没有用.讨厌,真的,它调用"只能在我的机器上工作"故障模式.呸.
| 归档时间: |
|
| 查看次数: |
1098 次 |
| 最近记录: |