COM, ATL

BSTR 자료형 고찰과 사용시 주의점

디버그정 2008. 8. 29. 11:26
BSTR은 자동화 타입에서 사용되는 문자열 자료형로서
메모리상에 처음 4바이트는 문자열의 길이값이 입력되고 그 후 유니코드의 문자열이 위치한다.

자동화(Automaton)에 사용되는 자료형의 하나이며
인터페이스에 dual 이나
automation(커스텀 인터페이스일지라도 이 속성을 주면 타입라이브러리 마샬링을 수행한다.)
속성이 존재하거나
dispinterface 등 IDispatch 관련 인터페이스인 경우 오토메이션 마샬러인 타입라이브러리 마샬링을 행할 것이다.

참고로 idl파일에서 [string] 속성을 주지 못한다. 이 속성을 주면 컴파일시 에러메시지가  검출된다.
메모리 할당과 해제는 CoTaskMemAlloc, CoTaskMemFree를 사용하지 않고
SysAllocString과 SysFreeString을 사용
한다.

사용례는

BSTR bstrStr=SysAllocString(L"무한도전");
//사용~~~~~
//.........
SysFreeString(bstrStr);

위와 같다.

참고로 인수로 사용시 bstrStr을 문자열 포인터 쓰듯이 사용하면 되었다.
실제로 bstrStr에 들어있는 값은 길이가 담긴 주소가 아니라
문자열의 첫 주소였다.
MessageBoxW(0, bstrStr, 0, 0);

그리고 대입연산을 하는 경우 두개의 변수가 메모리상에 할당된 문자열의 시작부분의 주소를 가리켰다.
물론 동일한 주소이다. 즉 대입할시에 깊은 복사를 하지 않는다.
BSTR bstrStr=SysAllocString(L"무한도전");
BSTR bstrOther=bstrStr;  // 변수값은 같은 주소를 가리키므로 동일하다.
SysFreeString(bstrStr);

사용할 경우는 wchar_t의 포인터형인 LPWSTR과 비슷하다.
문자열 시작위치 앞에 사이즈값이 4바이트로 위치하며,(포인터는 문자열 시작위치를 가리킨다.)
메모리할당, 해제가 Sys~계열의 api를 사용한다는 점 정도가 다르다.
컴포넌트 액티브X등 자동화시 문자열에 자주 사용하므로 익숙해지는 것도 좋을 것이다.

참고로 디스패치의 Invoke함수의 리턴값을 인수로 전달시 주의해야 할 점이 있다.
이 경우 CComBstr등의 래퍼 클래스를 사용하면 문제가 생길 소지가 있다.
CComBstr은 블록을 벗어난 경우 자동해제가 일어난다.
리턴값은 받는 측에서 해제해야 되는데 래퍼 클래스는 소멸자에서 자동해제(SysFreeString)를 하므로
받는 측에서 리턴값을 사용하기 전에 해제가 되버리거나, 받는 측에서 해제하고 위 소멸자에서 해제하는
중복해제가 일어날 수 있을 것이다.(메모리 접근 에러 가능성)