2011-08-25 8 views
3

나는 COM 메모리 관리에 관한 몇 가지 질문이 : 나는 COM 방법이COM 메모리 관리

  1. :

    STDMETHODIMP CWhitelistPolicy :: GetWebsitesStrings을 (SAFEARRAY ** 결과)

을 결과 = SAFEARRAY (BSTR). 다른 인터페이스 메서드 (* 결과를 설정하기 위해)에서 또 다른 SAFEARRAY (BSTR)를 받으면 * 결과와 외부 클라이언트에 전달하기 위해받은 문자열의 복사본을 만들어야합니까? 또는 내가 직접 문자열을 클라이언트에 전달할 수 있고 (그리고 소유권을 전달하는) 문자열을 사용하지 않을 것이라고 생각하십니까?

STDMETHODIMP CWhitelistPolicy::SetWebsitesStrings(SAFEARRAY* input) 

2.

여기서 I는 입력으로 BSTR 어레이를 수신한다. 다시 내 방법은 입력에 할당 된 메모리를 담당합니까?

STDMETHOD(SetUsers)(SAFEARRAY* input); 

3.

여기서 I는 다른 인터페이스 (SetUsers)의 메소드를 호출하고 I 입력 SAFEARRAY 메모리를 할당. SetUsers를 호출 한 후에는 SAFEARRAY를 처리 할 수 ​​있습니까? 마샬링이 발생하면 메모리가 항상 복사됩니까? (내 경우에는 SetUsers 메서드가 내 프로세스 내에서 COM DLL로 호스팅되는 인터페이스에서 호출됩니다.)

답변

3

이 질문에 대답하는 방법은 컴퓨터를 교차하는 COM 호출에 대해 생각하는 것입니다. 그렇다면 [out] 매개 변수는 분명합니다. 나는 호출자가 소유하고 원격 마샬링 계층이 그것을 수행 할 수 없으므로 메모리를 확보해야한다. [in] 매개 변수의 경우 마샬링 계층에서 내 데이터를 복사해야하며 원격 마샬링 계층은 전달한 데이터를 다시 사용할 수 없습니다.

COM의 핵심 신택스는 위치 중립성, 동일한 호출시 규칙입니다. 아파트는 컴퓨터에서 DCOM을 사용할 때의 규칙입니다. 당신은 무료로 책임

  1. 는 - 그것은 원격하고 원래의 데이터 복사본을하지 얻기 수 있기 때문에 당신이 다음 FNC를 호출 할 때 소유권을 전달하지 않습니다.

  2. 아니요 - 수신자로는 해제 할 필요가 없습니다. 그것이 아파트 내부라면 호출자가 제공 한 메모리이고 호출자는이를 해제해야합니다. 원격 호출 인 경우 서버 스텁은이를 할당하고 메서드가 반환 될 때이를 해제합니다.

  3. 예, 무료입니다. 아니요, 항상 복사되는 것은 아니기 때문에 2에 대한 대답이 아니오입니다. 복사 된 경우 스텁이 할당되고 스텁이이를 해제합니다. (가)이 경우에 대한 좀 더 자세한 내용은 Who owns returned BSTR? 질문 참조 -

참고 질문에 대한 내 대답은 [출력,] 매개 변수의 경우에는 적용되지 않았다.

Com allocation rules은 복잡하지만 합리적입니다. 모든 사례의 예를 이해하고 보려는 경우 Don Box가 책 "필수 com"을 가져옵니다. 그래도 실수를 저지르기 때문에 전략을 찾아야합니다. gflags (Windbg의 일부)와 힙 검사 플래그를 사용하여 double free가 발생하면 디버그 메시지가 표시되고 INT 3을 사용하여 호출이 중단 된 시점에서 실행을 중단합니다.Vstudio의 디버거는 실행 파일을 실행했을 때 디버거를 켜기 위해 사용했지만 여전히 이미지 옵션 탭에서 gflags를 사용하여 디버거를 강제 실행할 수 있습니다.

또한 누출을 감지하기 위해 UMDH (windbg의 일부 임) 사용법을 알아야합니다. DebugDiag은이 새로운 도구이며 사용하기가 더 쉽지만 슬프게도 32 비트 또는 64 비트 버전 만 설치할 수 있지만 둘 다 설치할 수는 없습니다.

그러면 캐시 된 BSTR은 힙과의 상호 작용이 지연되므로 이중 해제 및 누수 탐지를 어렵게 만듭니다. 환경 변수 OANOCACHE을 1로 설정하거나 함수 SetOaNoCache을 호출하여 ole 문자열 캐시를 종료 할 수 있습니다. 함수는 헤더 파일에 정의되어 있지 않으므로이 SO 질문 Where is SetOaNoCache defined?을 참조하십시오. 수락 된 대답은 GetProcAddress()를 통해 어려운 호출 방법을 보여줍니다. 받아 들여진 것의 밑에 응답은 당신이 필요로하는 모두가 oleaut32 수출 lib에있는 것과 같이 extern "C"다는 것을 보여준다. 마지막으로, 누수를 추적 할 때 캐시로 인해 발생하는 문제에 대한 자세한 설명은 this Larry Osterman 블로그 게시물을 참조하십시오.

+0

나를 위해 좀 더 명확하게 :-) - 입력으로받은 모든 메모리 (호출자의 관점에서 볼 때)는 내 소유권에 있지 않습니다. 즉 서버 스텁의 작업입니다. 출력 (호출자의 관점에서 볼 때)으로 전달되는 모든 메모리는 내 소유입니다. 즉, 전달 된 메모리를 릴리스해야하는 메서드 호출 이후에 누수가 발생합니다. – Ghita

+0

네가 준 경우에 그렇다. 들어오는 데이터를 수정하는 경우 [in, out] no. 들어오는 데이터를 수정하는 중입니다. 스텁은 호출자를 마샬링하기 전에 리턴 된 것을 해제하므로 들어오는 내용을 수정하려면 해방해야합니다. 나는 당신이 그것을 언제 잘못 생각하는지에 관한 다른 충고로 대답을 업데이트했다. –