TN017: 창 개체 소멸
이 참고에서는 메서드의 사용에 대해 설명합니다 CWnd::PostNcDestroy
. 파생 개체의 CWnd
사용자 지정 할당을 수행하려면 이 메서드를 사용합니다. 이 참고에서는 연산자 대신 delete
C++ Windows 개체를 삭제하는 데 사용해야 CWnd::DestroyWindow
하는 이유도 설명합니다.
이 문서의 지침을 따르는 경우 몇 가지 클린 문제가 발생합니다. 이러한 문제는 C++ 메모리를 삭제/해제하는 것을 잊거나, s와 같은 HWND
시스템 리소스를 해제하지 않거나, 개체를 너무 많이 해제하는 등의 문제로 인해 발생할 수 있습니다.
문제
각 windows 개체(파생 클래스 CWnd
의 개체)는 C++ 개체와 HWND
. C++ 개체는 애플리케이션의 힙에 할당되며 HWND
창 관리자가 시스템 리소스에 할당합니다. 창 개체를 삭제하는 방법에는 여러 가지가 있으므로 시스템 리소스 또는 메모리 누수 방지 규칙 집합을 제공해야 합니다. 또한 이러한 규칙은 개체와 Windows 핸들이 두 번 이상 제거되지 않도록 해야 합니다.
창 파괴
다음은 Windows 개체를 삭제하는 두 가지 허용된 방법입니다.
호출
CWnd::DestroyWindow
또는 Windows APIDestroyWindow
.연산자를 사용하여 명시적으로 삭제합니다
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
소멸자가 호출 DestroyWindow
m_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 연산자에 의해 해제됩니다.