"Warning: Calling DestroyWindow in CWnd::~CWnd" 처리하기(펌)

2015. 7. 2. 14:50IT-개발/winapi 및 MFC

반응형

멋진분이네요~ 사진도 올려놓고~ ㅋ. 핵심은 DestroyWindow()를 까먹지 말자~ ㅋㅋㅋ


간혹 개발을 하다 보면, 아래와 같은 메시지가 발생할 때가 있습니다. 

Warning: calling DestroyWindow in CWnd::~CWnd; OnDestroy or PostNcDestroy in derived class will not be called.


처음에는 저 메시지를 무시했었습니다. 프로그램이 동작하는 데에는 아무런 이상이 없었거든요. 
그러던 차에, 오늘 너무나 많은 경고 메시지가 나길래 한 번 없애기로 마음을 먹었습니다. 그리곤 다른 곳을 검색했지요. 그럼으로써 그와 파생되는 다른 지식을 얻어가게 되네요. 

위의 에러 메시지가 나타나는 경우는 CWnd를 상속받은 윈도우에서 DestroyWindow() 함수가 실행되지 않았을 경우입니다. 그런 경우를 살펴보면, 다음과 같습니다. 

1. CWnd 객체에 대해서 DestroyWindow()를 호출하지 않고, delete로 제거하려고 시도할 경우
2. CWnd를 상속받은 클래스의 소멸자에서 DestroyWindow를 호출하지 않은 경우


아시다시피 CWnd 클래스는 실제 윈도우 핸들인 m_hWnd를 포함하고 있고 m_hWnd에 대한 API 함수를 래핑해 주는 역할을 합니다. 때문에 CWnd를 완전히 삭제하려면, CWnd 객체를 delete 하는 것은 물론, 생성된 m_hWnd 윈도를 파괴시켜 주어야 합니다. 이 때, m_hWnd를 파괴하는 함수가 바로 DestroyWindow() 인 것이지요. 

그래서 1번의 경우, m_hWnd를 파괴하지 않고, CWnd 객체 만을 delete 하려고 했기 때문에 저런 이상한 에러를 뱉어내게 되는 것이지요. 
2번 역시 마찬가지로 CWnd를 상속받은 객체 자신이 지워지고 있는데, 윈도 핸들이 파괴되지 않았기 때문에 마찬가지로 에러를 뱉어냅니다. 

물론 이 경고 메시지는 디버그 상태에서만 나타납니다. 치명적이지는 않다는 뜻일까요? 실제로 저 사실을 모르고 작업을 해 왔지만, 이제껏 큰 문제를 만나보진 못했습니다. 그렇기에 오늘까지 몰랐던 것이겠지요. 
일반적으로 저런 에러가 나타나는 경우는 CWnd를 상속받아서 자기만의 컨트롤을 만든 경우입니다. 이 경우에 보통은 컨트롤을 생성하면서 자신을 컨트롤의 부모로 설정합니다. 그래야만 컨트롤에서 발생하는 메시지를 받아서 처리할 수 있겠지요. 그것이 위의 경고가 치명적이지 않은 이유입니다. 
윈도가 파괴될 때에는 모든 자식 윈도를 먼저 파괴시킨 이후에 자신이 파괴됩니다. 그렇게 되면 설사 CWnd 를 상속받은 객체에서 DestroyWindow 함수를 호출하지 않더라도, 부모가 파괴되면서 자식이 모두 파괴되기 때문에 결국은 윈도가 파괴되는 것입니다. 

저것이 문제가 될 경우는 CWnd를 상속받은 클래스의 객체를 Create 할 때, 부모를 NULL (데스크탑 윈도)로 설정하는 경우라 할 수 있겠네요. 이 경우에는 메인 윈도가 파괴된다고 하더라도 CWnd를 상속받은 객체의 윈도는 파괴되지 않을 테니, 메모리 릭이 생길 것이라 봅니다. 

어쨌든, MS가 나름 애써서(?) 보고하는 에러이니 가능하면 나오지 않도록 하는 것이 더 낫겠지요. 

위 에러에 대한 자세한 글은 다음의 페이지에서 볼 수 있습니다. 
http://support.microsoft.com/kb/105081
또한 다음의 링크에서 DestroyWindow() 에 대한 도움말을 볼 수 있습니다.
http://msdn2.microsoft.com/ko-kr/library/kt7c0708(VS.80).aspx