And*_*son 6 c# c++ com interop atl
我有一个用C++编写的进程外COM服务器,它由一些C#客户端代码调用.其中一个服务器接口上的方法将大型BSTR返回给客户端,我怀疑这会导致内存泄漏.该代码有效,但我正在寻找有关编组BSTR的帮助.
简化一下,服务器方法的IDL是
HRESULT ProcessRequest([in] BSTR request, [out] BSTR* pResponse);
Run Code Online (Sandbox Code Playgroud)
并且实现如下:
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;
}
Run Code Online (Sandbox Code Playgroud)
A2BSTR在内部使用SysAllocStringLen()分配BSTR.
在C#客户端中,我只需执行以下操作:
string request = "something";
string response = "";
myserver.ProcessRequest(request, out response);
DoSomething(response);
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为请求字符串被发送到COM服务器并且正确的响应字符串被返回给C#客户端.但是每次往服务器的往返都会泄漏服务器进程中的内存.crt泄漏检测支持显示crt堆上没有重大泄漏,所以我怀疑泄漏是用IMalloc分配的.
我在这里做错了吗?我发现含糊的评论说'所有的参数必须用CoTaskMemAlloc分配,否则互操作编组将不会释放它'但没有细节.
安迪
安尼尔森已经很好地阐述了这一点,但我想补充几点;
CoTaskMemAlloc 不是唯一的 COM 友好分配器——BSTR 被默认编组器识别,并且将使用 SysAllocString 等来释放/重新分配。
避免 USES_CONVERSION (由于堆栈溢出风险 - 请参阅 anelson 的答案),您的完整代码应该是这样的 [1]
(请注意,A2BSTR 可以安全使用,因为它在转换后调用 SysAllocString,并且不使用动态堆栈分配。此外,使用数组删除 (delete[]),因为 BuildResponse 可能会分配一个字符数组)
[1]
HRESULT MyClass::ProcessRequest(BSTR request, BSTR* pResponse)
{
char* pszResponse = BuildResponse(CW2A(request));
*pResponse = A2BSTR(pszResponse);
delete[] pszResponse;
return S_OK;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4449 次 |
| 最近记录: |