CAxWindow 사용시 주의사항 & ATL Containment BUG
개발 2007. 11. 20. 11:24날짜 : 2007-11-20
저자 : hanburn
ATL 프로그램으로 WebBrowser 컨트롤을 hosting 하는 역할로 CAxWindow를 많이 사용합니다. 이 CAxWindow를 사용할때 주의를 기울이지 않으면 메모리릭(memory leak)이 발생할 수 있다고 합니다. 그리고 CAxWindow의 자체적인 버그도 있다고 합니다.
먼저, 다음은 메모리릭이 발생할 수 있는 잘못된 2가지 사용예입니다.
1번사용예
//Intialize ATL control containment.
AtlAxWinInit();
//Create container window.
HWND hWndCont = m_ax.Create(m_hWnd, rect, 0, WS_CHILD | WS_VISIBLE);
//Create & activate ActiveX control
HRESULT hr = m_ax.CreateControl("MSCAL.Calendar");
2번사용예
//Intialize ATL control containment.
AtlAxWinInit();
//Create container window
HWND hWndCont = m_ax.Create(m_hWnd, rect, 0, WS_CHILD | WS_VISIBLE);
// Create ActiveX control.
CComPtr<IUnknown> spunk;
HRESULT hr = CLSIDFromProgID(OLESTR("MSCAL.Calendar"), &clsid);
hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_IUnknown, (void**)&spunk);
// Activate ActiveX control.
HRESULT hr = m_ax.AttachControl(spunk);
위의 두 경우에 Create()함수는 CAxHostWindow 객체를 생성합니다. CreateControl()함수나 AttachControl()함수 또한 CAxHostWindow 객체를 생성합니다. 따라서 처음에 Create() 함수로 생성된 CAxHostWindow 객체는 소멸이 않되게 됩니다.
다음으로 ATL Containment의 메모리릭 버그입니다.
증상 : ActiveX를 ATL에서 hosting 할때에 메모리가 줄줄이 샘.
원인 : ATL내부에서 CreateAcceleratorTable 함수를 호출하는데 소멸시(release)시에 ATL에서 이것을 해제하지 않아서 발생함.
대책 :
1. Atlhost.h파일의 복사본을 만들어서 Fixatlhost.h 파일을 만든다.
2. FixAtlhost.h파일에 CAxHostWindow 클래스에 HACCEL타입의 멤버 변수를 하나 추가한다.
3. IOleInPlaceSite::GetWindowContext 메소드에서 CreateAcceleratorTabel함수의 반환값을 저장해 둔다.
4. IOleInPlaceSite::OnInPlaceDeactivate 메소드에서(Release되는 시점) DestroyAcceleratorTable함수를 호출해준다.
5. FixAtlhost.h 파일을 저장하고 atlhost.h 파일대신 include를 한다.
참고자료 :
http://support.microsoft.com/kb/229904 : CAxWindow Members Can Cause a Memory Leak
http://support.microsoft.com/kb/258235 : Memory Leak with ATL Containment