我有一个用 C++ 编写的进程外 COM 服务器,由一些 C# 客户端代码调用。服务器接口之一上的方法向客户端返回一个大的 BSTR,我怀疑这会导致内存泄漏。该代码有效,但我正在寻求有关编组 BSTR 的帮助。
稍微简化一下,服务器方法的 IDL 是
HRESULT ProcessRequest([in] BSTR request, [out] BSTR* pResponse);
其实现如下所示:
HRESULT MyClass::ProcessRequest(BSTR request, BSTR* pResponse)
{
USES_CONVERSION;
char* pszRequest = OLE2A(request);
char* pszResponse = BuildResponse(pszRequest);
delete pszRequest;
*pResponse = A2BSTR(pszResponse);
delete pszResponse;
return S_OK;
}
A2BSTR 使用 SysAllocStringLen() 在内部分配 BSTR。
在 C# 客户端中,我只需执行以下操作:
string request = "something";
string response = "";
myserver.ProcessRequest(request, out response);
DoSomething(response);
这是有效的,因为请求字符串被发送到 COM 服务器,并且正确的响应字符串被返回到 C# 客户端。但是每次到服务器的往返都会泄漏内存server过程。 crt 泄漏检测支持显示 crt 堆上没有重大泄漏,因此我怀疑泄漏是通过 IMalloc 分配的。
我在这里做错了什么吗?我发现了一些模糊的评论:“所有输出参数必须使用 CoTaskMemAlloc 进行分配,否则互操作编组器将不会释放它们”,但没有详细信息。
Andy
我没有看到你的代码有明显的问题。建议您修改 ProcessRequest 方法以排除 COM 互操作作为泄漏源:
HRESULT MyClass::ProcessRequest(BSTR request, BSTR* pResponse)
{
*psResponse = ::SysAllocStringLen(L"[suitably long string here]");
return S_OK;
}
我怀疑这不会泄漏,在这种情况下,您已经将泄漏范围缩小到了您的代码。
我还注意到 OLE2A 在堆栈上分配内存,因此您不仅不应该删除 pszRequest,而且根本不应该使用 OLE2A,因为堆栈溢出的可能性。看本文以获得更安全的替代品。
我还建议您将 A2BSTR 替换为 ::SysAllocString(CA2W(pszResponse))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)