CoTaskMemAlloc v malloc v AllocHGlobal [英] CoTaskMemAlloc v malloc v AllocHGlobal

查看:40
本文介绍了CoTaskMemAlloc v malloc v AllocHGlobal的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经读到在Windows上,malloc与CoTaskMemAlloc不同,后者与AllocHGlobal不同.对于C#使用者,这据说意味着,如果我有一个返回malloc指针的C函数,则需要对其进行免费调用.如果我P/Invoke并指定了字符串返回类型,则CLR应该调用CoTaskMemFree,并且在基于malloc的指针上应该失败.

I've read that on Windows, malloc is different from CoTaskMemAlloc, which is different from AllocHGlobal. For C# consumers, this supposedly means if I've got a C function that returns a malloc'd pointer, I need to call free on it. If I P/Invoke and specify a string return type, the CLR is supposed to call CoTaskMemFree and should fail on a malloc'd pointer.

但是,我在实践中看不到这一点.我创建了一个仅返回malloc的char *并将其P/调用为字符串的DLL.没有内存泄漏.的确,无论我做什么,我都不会失败.我叫malloc,GlobalHAlloc,CoTaskMemAlloc,然后使用任何免费的实现,一切都可以正常工作.没有内存泄漏.重复使用相同的内存空间.

However, I'm not able to see this in practice. I created a DLL that just returns a malloc'd char* and P/Invoked it as a string. No memory leak. Indeed, no matter what I try, I cannot get things to fail. I call malloc, GlobalHAlloc, CoTaskMemAlloc, then use any free implementation and things just work. No memory leak. Same memory space is re-used.

如何强制此操作失败?还是这应该被实现定义"的东西之一,但实际上只是一种方法?

How can I force this to fail? Or is this one of those things that's supposed to be "implementation defined" but in reality just works one way?

这是在VS2015 Update 2,Windows 8.1上.

This is on VS2015 Update 2, Windows 8.1.

推荐答案

这肯定不起作用.但是情况一直在变.C运行时库在VS2012中已更改,并且不再创建自己的堆.对于VS2015,此C:\ Program Files(x86)\ Windows Kits \ 10 \ Source \ 10.0.10240.0 \ ucrt \ heap \ heap_handle.cpp中的代码是相关的:

This certainly did not used to work. But things have been changing. The C runtime library was changed in VS2012 and it no longer creates its own heap anymore. For VS2015, this code in C:\Program Files (x86)\Windows Kits\10\Source\10.0.10240.0\ucrt\heap\heap_handle.cpp is relevant:

// 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;
}

请注意对GetProcessHeap()的调用,它返回Marshal.AllocHGlobal()从其分配的同一堆.因此,是的,使用Marshal.FreeHGlobal()取消分配时,您不会从调试堆中获取异常,也不会泄漏.

Note the call to GetProcessHeap(), it returns the same heap that Marshal.AllocHGlobal() allocates from. So yes, you are not going to get an exception from the debug heap nor a leak when you de-allocate with Marshal.FreeHGlobal().

CoTaskMemAlloc()几乎相同.单步进入该功能,我会看到:

Much the same for CoTaskMemAlloc(). Single-stepping into the function, I see:

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)] 

请注意 g_hHeap 变量的用法.我看到它具有与GetProcessHeap()返回相同的值.同样,使用 any 的释放函数释放也可以正常工作.

Note the usage of the g_hHeap variable. I see it have the same value as GetProcessHeap() returns. So again, releasing with any of the deallocation functions is going to work just fine.

请注意,这是我从Windows 10上获得的,较旧版本的Windows不会以相同的方式运行.并注意CRetailMalloc_Alloc,这是一种不太愉快的随机化方法,具有不可预测的用法.

Do note that this I got this from Windows 10, an older version of Windows is not going to behave the same way. And note CRetailMalloc_Alloc, a not so pleasant randomizer with an unpredictable usage.

虽然这肯定是有帮助的,但程序失败的方式要少得多,但是当您测试应用程序时,它实际上并没有用.确实很讨厌,它调用仅在我的机器上可用"故障模式.ah.

While this was certainly meant to be helpful, a lot less ways in which programs can fail, it isn't actually useful when you test your app. Nasty, really, it invokes the "only works on my machine" failure mode. Bah.

这篇关于CoTaskMemAlloc v malloc v AllocHGlobal的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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