何时适合使用CoTaskMemAlloc?能否举个例子?
当从本机 C++ 库返回 char* 作为字符串到 .NET 时,请使用 CoTaskMemAlloc。
C#
[DllImport("test.dll", CharSet=CharSet.Ansi)]
extern static string Foo();
C
char* Foo()
{
std::string response("response");
int len = response.length() + 1;
char* buff = (char*) CoTaskMemAlloc(len);
strcpy_s(buff, len, response.c_str());
return buff;
}
由于.NET使用CoTaskMemFree,您必须像这样分配字符串,不能使用malloc / new在堆栈上或堆上分配。
Foo()
返回的资源何时被释放?或者需要手动释放吗? - chtenb哇,我得想一会儿才能理解这个 -- 我曾经用 ATL 做过一些小型 COM 编程,很少需要使用它。
不过,我想到了一个情况:Windows Shell 扩展。如果你正在处理一组文件系统对象,你可能需要处理 PIDLs (指向 ID 列表的指针)。这些是奇怪的小型文件系统对象抽象,需要使用一个支持 COM 的分配器(如 CoTaskMemAlloc
)显式地进行分配和释放。还有另一种选择,即从 SHGetMalloc
(已弃用) 或 CoGetMalloc
获取的 IMalloc
接口指针 -- 它只是一个抽象层,可以使用任何适当的内存分配器,使您的代码不会绑定到特定的内存分配器。
使用 CoTaskMemAlloc
或 IMalloc
而不是 malloc()
的原因是,内存分配/释放需要是“COM-aware”,以便在运行时一致地执行它们的分配和释放,即使分配和释放是由完全不相关的代码 (例如 Windows 为您的 C++ 代码分配内存,然后释放,或者您的 C++ 代码分配内存,将其传输到其他人的 VB 代码,然后释放)。 malloc()
和 new
都不能与系统的运行时堆互操作,因此您不能使用它们来分配内存以传输到其他 COM 对象,也不能接收其他 COM 对象的内存并进行释放。
以下调用最终都会得到相同的分配,因此很少会出错:
CoTaskMemAlloc/SHAlloc -> IMalloc.Alloc -> GlobalAlloc(GMEM_FIXED)
malloc()
时,才会出现问题。CoTaskMemAlloc
进行 COM 调用(例如分配 FORMATETC.ptd 字段)。GlobalAlloc()
。这种情况将一直持续到剪贴板 API 和 COM STGMEDIUM 之间的冲突得到解决。GlobalAlloc
和 CoTaskMemAlloc
使用相同的堆,即 GetProcessHeap
就足够了。这些包装函数可以在不破坏 STGMEDIUM
的情况下添加不同的功能。 - MSalters