2009-08-19 11 views
6

일부 C# 클라이언트 코드에서 호출되는 C++로 작성된 독립 프로세스 COM 서버가 있습니다. 서버의 인터페이스 중 하나에있는 메서드는 클라이언트에 큰 BSTR을 반환하고 이것이 메모리 누수의 원인이 아닌지 의심 스럽습니다. 이 코드는 작동하지만 BSTR을 마샬링 아웃하는 데 도움을 찾고 있습니다. 약간 단순화COM interop을 사용하여 C++에서 C#으로 BSTR을 마샬링

서버 메소드에 대한 IDL은

HRESULT ProcessRequest([in] BSTR request, [out] BSTR* pResponse); 

이며처럼 구현 같습니다 A2BSTR 내부적 SysAllocStringLen를 사용 BSTR()을 할당

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; 
} 

. 단순히 다음을 수행 C#을 클라이언트에서

: 요청하는 문자열의

string request = "something"; 
string response = ""; 
myserver.ProcessRequest(request, out response); 
DoSomething(response); 

이 작품은 COM 서버와 올바른 응답 문자열로 전송받을는 C# 클라이언트에 반환됩니다. 그러나 서버에 왕복 할 때마다 서버 프로세스의 메모리가 누수됩니다. crt 누수 탐지 지원은 crt 힙에 중요한 누수가 없음을 보여 주므로 누출이 IMalloc로 할당되었다고 의심됩니다.

여기에 뭐가 잘못 되었나요? 나는 모든 매개 변수가 CoTaskMemAlloc으로 할당되어야한다는 모호한 의견을 발견했다. 그렇지 않으면 interop marshaller가이를 해제하지 않을 것이지만 세부 사항은 없다.

앤디

+0

이 질문에 대한 감사 답변 내가 ATL COM 개체와 C++로 BSTR을 사용하고있다. 내가 발견 한 한 가지는 IDL에서 BSTR *을 [out]으로 지정하면 전달 된 BSTR *이 초기화되면 메모리 누수가 발생한다는 것입니다. 따라서 IDL 파일에서 BSTR *을 [in, out]으로 선언해야합니다. http://msdn.microsoft.com/en-us/library/bdyd6xz6.aspx –

답변

2

A2BSTR 교체 건의 할 것입니다,하지만 난 점 몇 가지를 추가하고 싶었;

  • CoTaskMemAlloc 유일한 COM 친화적 할당되지 않습니다 - BSTR에 기본 마샬에 의해 인식하고 해제됩니다/재 할당 SysAllocString에게 & 친구를 사용하여.(오버 플로우의 위험을 스택에 의한 - anelson의 답변을 참조) USES_CONVERSION을 방지

  • 는 전체 코드는 [1]

(A2BSTR이 호출로 사용하는 것이 안전주의 같은 것을해야한다 변환 후 SysAllocString, 동적 스택 할당을 사용하지 않는다. BuildResponse이 가능성 BSTR 할당이 나타나게 할 수있는 캐쉬를

  • 문자의 배열)를 할당으로서도 (삭제 []) 배열 - 삭제 사용 마치 메모리 누수가있는 것처럼 자세한 내용은 http://support.microsoft.com/kb/139071을 참조하거나 Google for OANOCACHE를 참조하십시오. 캐시를 비활성화하고 '누출'이 사라지는 지 확인할 수 있습니다.

[1]

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

고마워요. 나는 당신이 제안한 변화를 만들었습니다. 그래도 누수가있는 것처럼 보입니다. –

-4

난 당신이 ::SysFreeString()request을 파괴해야 할 것 같아요. 이 메모리는 서버 측에 할당됩니다.

또한 OLE2A은 변환으로 인해 메모리를 할당 할 수 있습니다 (보세요). 당신은 또한 그것을 풀지 않습니다.

+0

응답 해 주셔서 감사합니다. '요청'을 다시 파괴하면서 호출자가 [in] 매개 변수를 할당하고 해제했다고 생각했습니다. –

+0

아니요, COM 규칙에 따라 수신자는 [in] 매개 변수를 절대로 사용하지 않습니다. – anelson

+0

OLE2A는 스택에 메모리를 동적으로 할당하는 _alloca를 사용합니다. 문자열의 크기가 알려지지 않았지만 할당 해제가 필요하지 않은 경우 위험 할 수 있습니다. 함수가 끝나면 스택 공간이 다시 확보됩니다. –

3

코드에 명백한 문제가 나타나지 않습니다. 당신은 누출의 소스로 COM 상호 운용성을 배제하기 위해 processRequest 메소드를 수정 제안 :

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

나는 당신이 당신의 코드에 누수를 축소 한 경우에, 그 누출되지 않습니다 생각한다.

또한 OLE2A가 스택에 메모리를 할당하므로 pszRequest를 삭제하면 안되지만 스택 오버플로 가능성으로 인해 OLE2A를 사용하지 않아야합니다. 더 안전한 대안에 대해서는 this article을 참조하십시오.

나 또한 당신과 함께 :: SysAllocString (CA2W (pszResponse)) anelson이 꽤 잘 덮여있다

+0

감사합니다. 그 누출처럼 보이지만 COM 메모리 처리, 어디 있는지 모르겠습니다. boundschecker 시도 시간 ... –

관련 문제