Mam out-of-process serwera COM napisany w C++, który jest wywoływany przez jakiś kod klienta C#. Metoda na jednym z interfejsów serwera zwraca klientowi duży BSTR i podejrzewam, że powoduje to przeciek pamięci. Kod działa, ale szukam pomocy w wydzielaniu BSTR.Marshalling BSTRs od C++ do C# z interopem COM
Upraszczając nieco, IDL dla metody serwer jest
HRESULT ProcessRequest([in] BSTR request, [out] BSTR* pResponse);
i realizacja wygląda następująco:
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 wewnętrznie przydziela BSTR korzystając SysAllocStringLen().
W C# klienta po prostu wykonaj następujące czynności:
string request = "something";
string response = "";
myserver.ProcessRequest(request, out response);
DoSomething(response);
To działa, ponieważ ciągi żądanie wysyłane do serwera COM i prawidłowych ciągów odpowiedzi są zwracane do C# klienta. Jednak każda runda podróży do serwera powoduje wyciek pamięci w procesie serwera. Obsługa wykrywania przecieków crt nie wykazuje znaczących wycieków na stercie crt, więc podejrzewam, że przeciek został przydzielony za pomocą IMalloc.
Czy robię coś złego tutaj? Znalazłem niejasne komentarze, że "wszystkie parametry muszą zostać przydzielone za pomocą CoTaskMemAlloc, w przeciwnym razie interlokator nie uwolni ich", ale bez szczegółów.
Andy
Dzięki za to pytanie i odpowiedzi, jak używam BSTR z obiektem COM ATL i C++. Jedną z rzeczy, którą odkryłem, było to, że jeśli podasz BSTR * jako [out] w IDL, to jeśli został pomyślnie wprowadzony BSTR *, dostaniesz wycieku pamięci. Dlatego musisz zadeklarować BSTR * jako [w, out] w pliku IDL. Zobacz http://msdn.microsoft.com/en-us/library/bdyd6xz6.aspx –