TN017: 창 개체 소멸

이 참고에서는 메서드의 사용에 대해 설명합니다 CWnd::PostNcDestroy . 파생 개체의 CWnd사용자 지정 할당을 수행하려면 이 메서드를 사용합니다. 이 참고에서는 연산자 대신 delete C++ Windows 개체를 삭제하는 데 사용해야 CWnd::DestroyWindow 하는 이유도 설명합니다.

이 문서의 지침을 따르는 경우 몇 가지 클린 문제가 발생합니다. 이러한 문제는 C++ 메모리를 삭제/해제하는 것을 잊거나, s와 같은 HWND시스템 리소스를 해제하지 않거나, 개체를 너무 많이 해제하는 등의 문제로 인해 발생할 수 있습니다.

문제

각 windows 개체(파생 클래스 CWnd의 개체)는 C++ 개체와 HWND. C++ 개체는 애플리케이션의 힙에 할당되며 HWND창 관리자가 시스템 리소스에 할당합니다. 창 개체를 삭제하는 방법에는 여러 가지가 있으므로 시스템 리소스 또는 메모리 누수 방지 규칙 집합을 제공해야 합니다. 또한 이러한 규칙은 개체와 Windows 핸들이 두 번 이상 제거되지 않도록 해야 합니다.

창 파괴

다음은 Windows 개체를 삭제하는 두 가지 허용된 방법입니다.

  • 호출 CWnd::DestroyWindow 또는 Windows API DestroyWindow.

  • 연산자를 사용하여 명시적으로 삭제합니다 delete .

첫 번째 사례는 지금까지 가장 일반적입니다. 이 사례는 코드가 직접 호출 DestroyWindow 하지 않는 경우에도 적용됩니다. 사용자가 프레임 창을 직접 닫으면 이 작업은 WM_CLOSE 메시지를 생성하고 이 메시지에 대한 기본 응답은 호출 DestroyWindow하는 것입니다. 부모 창이 제거되면 Windows는 모든 자식을 호출 DestroyWindow 합니다.

두 번째 경우, Windows 개체에서 연산자를 delete 사용하는 경우는 드물어야 합니다. 다음은 사용 delete 이 올바른 선택인 경우입니다.

다음으로 자동 클린CWnd::PostNcDestroy

시스템에서 Windows 창을 삭제하면 창으로 전송된 마지막 Windows 메시지는 다음과 같습니다 WM_NCDESTROY. 해당 메시지의 기본 CWnd 처리기는 .입니다 CWnd::OnNcDestroy. OnNcDestroy 는 C++ 개체에서 분리 HWND 하고 가상 함수 PostNcDestroy를 호출합니다. 일부 클래스는 이 함수를 재정의하여 C++ 개체를 삭제합니다.

기본 구현 CWnd::PostNcDestroy 은 아무 작업도 수행하지 않습니다. 이는 스택 프레임에 할당되거나 다른 개체에 포함된 창 개체에 적합합니다. 이 동작은 다른 개체가 없는 힙에서 할당하도록 설계된 창 개체에는 적합하지 않습니다. 즉, 다른 C++ 개체에 포함되지 않은 창 개체에는 적합하지 않습니다.

힙에서만 할당하도록 설계된 클래스는 메서드를 재정의 PostNcDestroy 하여 수행합니다 delete this;. 이 문은 C++ 개체와 연결된 모든 메모리를 해제합니다. 기본 CWnd 소멸자가 호출 DestroyWindowm_hWnd 하지 NULL않더라도 이 호출은 핸들이 분리 NULL 되고 클린 단계 동안 무한 재귀로 이어지지 않습니다.

참고 항목

시스템은 일반적으로 Windows WM_NCDESTROY 메시지를 처리한 후 호출 CWnd::PostNcDestroy 되고 HWND C++ 창 개체는 더 이상 연결되지 않습니다. 또한 오류 발생 시 시스템은 대부분의 CWnd::Create 호출 구현에서 호출 CWnd::PostNcDestroy 합니다. 자동 클린업 규칙은 이 문서의 뒷부분에 설명되어 있습니다.

자동 클린up 클래스

다음 클래스는 자동 클린용으로 설계되지 않았습니다. 일반적으로 다른 C++ 개체 또는 스택에 포함됩니다.

  • 모든 표준 Windows 컨트롤(CStatic, CEdit, CListBox등).

  • 직접 CWnd 파생된 자식 창(예: 사용자 지정 컨트롤)입니다.

  • 분할자 창(CSplitterWnd).

  • 기본 컨트롤 막대(파생된 CControlBar클래스, 컨트롤 막대 개체에 대해 자동 삭제를 사용하도록 설정하려면 Technical Note 31 참조).

  • 스택 프레임의 모달 대화용으로 설계된 대화 상자(CDialog)입니다.

  • 를 제외한 CFindReplaceDialog모든 표준 대화 상자

  • ClassWizard에서 만든 기본 대화 상자입니다.

다음 클래스는 자동 클린 위해 설계되었습니다. 일반적으로 힙에 자체적으로 할당됩니다.

  • 주 프레임 창(직접 또는 간접적으로 CFrameWnd파생됨).

  • 창 보기(직접 또는 간접적으로 CView파생됨)

이러한 규칙을 위반하려면 파생 클래스의 메서드를 재정의 PostNcDestroy 해야 합니다. 클래스에 자동 클린 추가하려면 기본 클래스를 호출한 다음 delete this;. 클래스에서 자동 클린 제거하려면 직접 기본 클래스의 PostNcDestroy 메서드 대신 직접 호출 CWnd::PostNcDestroy 합니다.

자동 클린up 동작을 변경하는 가장 일반적인 용도는 힙에 할당할 수 있는 모덜리스 대화 상자를 만드는 것입니다.

delete를 호출하는 경우

C++ 메서드 또는 전역 DestroyWindow API인 Windows 개체를 삭제하도록 호출 DestroyWindow 하는 것이 좋습니다.

MDI 자식 창을 삭제하기 위해 전역 DestroyWindow API를 호출하지 마세요. 대신 가상 메서드 CWnd::DestroyWindow 를 사용해야 합니다.

자동 클린up을 수행하지 않는 C++ Window 개체의 경우 올바르게 파생된 클래스를 가리키지 않는 경우 VTBL 소멸자에서 CWnd::~CWnd 호출 DestroyWindow 하려고 할 때 연산자를 사용하면 delete 메모리 누수 발생이 발생할 수 있습니다. 시스템이 호출할 적절한 삭제 방법을 찾을 수 없기 때문에 누수가 발생합니다. 대신 delete 사용하면 DestroyWindow 이러한 문제를 방지할 수 있습니다. 이 오류는 미묘할 수 있으므로 디버그 모드에서 컴파일하면 위험에 처한 경우 다음 경고가 생성됩니다.

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

자동 클린 수행하는 C++ Windows 개체의 경우 호출DestroyWindow해야 합니다. 연산자를 delete 직접 사용하는 경우 MFC 진단 메모리 할당자는 메모리를 두 번 해제하고 있음을 알립니다. 두 가지 항목은 첫 번째 명시적 호출과 자동 클린up 구현에서 간접 호출 delete this; 입니다PostNcDestroy.

자동 클린up이 아닌 개체를 호출 DestroyWindow 한 후에도 C++ 개체는 계속 주위에 있지만 m_hWnd 됩니다NULL. 자동 클린up 개체를 호출 DestroyWindow 하면 C++ 개체가 사라집니다. 이 개체는 자동 클린up 구현PostNcDestroy에서 C++ delete 연산자에 의해 해제됩니다.

참고 항목

숫자별 기술 노트
범주별 기술 정보