CoTaskMemAlloc v malloc v AllocHGlobal
CoTaskMemAlloc v malloc v AllocHGlobal
我在 Windows 上读到过,malloc 不同于 CoTaskMemAlloc,后者又不同于 AllocHGlobal。对于 C# 使用者,这可能意味着如果我有一个 return 是 malloc 指针的 C 函数,我需要对其调用 free。如果我 P/Invoke 并指定一个字符串 return 类型,CLR 应该调用 CoTaskMemFree 并且应该在 malloc 指针上失败。
但是,我无法在实践中看到这一点。我创建了一个 DLL,它只是 returns 一个 malloc'd char* 和 P/Invoked 它作为一个字符串。没有内存泄漏。事实上,无论我尝试什么,我都不能让事情失败。我调用 malloc、GlobalHAlloc、CoTaskMemAlloc,然后使用任何免费的实现,一切正常。没有内存泄漏。相同的内存 space 被重新使用。
我怎样才能强制它失败?或者这是应该是 "implementation defined" 但实际上只是以一种方式工作的事情之一?
这是在 VS2015 更新 2 上,Windows 8.1.
这个肯定没用过。但事情一直在变化。 C 运行时库 was changed in VS2012,它不再创建自己的堆。对于 VS2015,C:\Program Files (x86)\Windows Kits\Source.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;
}
注意对 GetProcessHeap() 的调用,它 returns 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)]
注意 g_hHeap
变量的用法。我看到它与 GetProcessHeap() returns 具有相同的值。因此,再次使用 任何 释放函数都可以正常工作。
请注意,这是我从 Windows 10 得到的,Windows 的旧版本不会以同样的方式运行。并注意 CRetailMalloc_Alloc,一个不太令人愉快的随机化器,其用法不可预测。
虽然这当然是有帮助的,但程序失败的方式要少得多,但在您测试应用程序时它实际上并没有用。真的很讨厌,它调用了 "only works on my machine" 故障模式。呸
我在 Windows 上读到过,malloc 不同于 CoTaskMemAlloc,后者又不同于 AllocHGlobal。对于 C# 使用者,这可能意味着如果我有一个 return 是 malloc 指针的 C 函数,我需要对其调用 free。如果我 P/Invoke 并指定一个字符串 return 类型,CLR 应该调用 CoTaskMemFree 并且应该在 malloc 指针上失败。
但是,我无法在实践中看到这一点。我创建了一个 DLL,它只是 returns 一个 malloc'd char* 和 P/Invoked 它作为一个字符串。没有内存泄漏。事实上,无论我尝试什么,我都不能让事情失败。我调用 malloc、GlobalHAlloc、CoTaskMemAlloc,然后使用任何免费的实现,一切正常。没有内存泄漏。相同的内存 space 被重新使用。
我怎样才能强制它失败?或者这是应该是 "implementation defined" 但实际上只是以一种方式工作的事情之一?
这是在 VS2015 更新 2 上,Windows 8.1.
这个肯定没用过。但事情一直在变化。 C 运行时库 was changed in VS2012,它不再创建自己的堆。对于 VS2015,C:\Program Files (x86)\Windows Kits\Source.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;
}
注意对 GetProcessHeap() 的调用,它 returns 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)]
注意 g_hHeap
变量的用法。我看到它与 GetProcessHeap() returns 具有相同的值。因此,再次使用 任何 释放函数都可以正常工作。
请注意,这是我从 Windows 10 得到的,Windows 的旧版本不会以同样的方式运行。并注意 CRetailMalloc_Alloc,一个不太令人愉快的随机化器,其用法不可预测。
虽然这当然是有帮助的,但程序失败的方式要少得多,但在您测试应用程序时它实际上并没有用。真的很讨厌,它调用了 "only works on my machine" 故障模式。呸