簡體   English   中英

使用COM互操作編組從C ++到C#的BSTR

[英]Marshalling BSTRs from C++ to C# with COM interop

我有一個用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#客戶端。 但是每次往服務器的往返都會泄漏服務器進程中的內存。 crt泄漏檢測支持顯示crt堆上沒有重大泄漏,所以我懷疑泄漏是用IMalloc分配的。

我在這里做錯了嗎? 我發現含糊的評論說'所有的參數必須用CoTaskMemAlloc分配,否則互操作編組將不會釋放它'但沒有細節。

安迪

我沒有看到您的代碼存在明顯問題。 建議您修改ProcessRequest方法以排除COM interop作為泄漏源:

HRESULT MyClass::ProcessRequest(BSTR request, BSTR* pResponse)
{
    *psResponse = ::SysAllocStringLen(L"[suitably long string here]");
    return S_OK;
}

我懷疑它不會泄漏,在這種情況下,你已經縮小了代碼的泄漏范圍。

我還注意到OLE2A在堆棧上分配內存,因此不僅不應該刪除pszRequest,而且由於堆棧溢出的可能性,你根本不應該使用OLE2A。 有關更安全的替代方案,請參閱此文

我還建議你用:: SysAllocString(CA2W(pszResponse))替換A2BSTR

阿內爾森已經很好地介紹了這一點,但我想補充幾點;

  • CoTaskMemAlloc不是唯一的COM友好分配器 - BSTR由默認的編組器識別,並將使用SysAllocString和朋友釋放/重新分配。

  • 避免使用USES_CONVERSION(由於堆棧溢出風險 - 請參閱anelson的回答),您的完整代碼應該是這樣的[1]

(請注意,A2BSTR可以安全使用,因為它在轉換后調用SysAllocString,並且不使用動態堆棧分配。另外,使用array-delete(delete []),因為BuildResponse可能會分配一個chars數組)

  • BSTR分配器有一個緩存,可以使其看起來好像存在內存泄漏。 有關詳細信息,請參閱http://support.microsoft.com/kb/139071 ;有關OANOCACHE,請參閱Google。 您可以嘗試禁用緩存,看看“泄漏”是否消失。

[1]

HRESULT MyClass::ProcessRequest(BSTR request, BSTR* pResponse)
{
    char* pszResponse = BuildResponse(CW2A(request));
    *pResponse = A2BSTR(pszResponse);
    delete[] pszResponse;
    return S_OK;
}

我猜你需要用::SysFreeString()來銷毀request 該內存在服務器端分配。

此外, OLE2A可能會因轉換而分配內存(看一看)。 你也不要釋放它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM