Udostępnij za pośrednictwem


TN017: Niszczących obiekty okna

Uwaga ta opisuje korzystanie z CWnd::PostNcDestroy metody.Użyj tej metody, jeśli chcesz zrobić dostosowanych alokacji CWnd-pochodzących z obiektów.Uwaga Ta wyjaśniono, dlaczego należy korzystać z CWnd::DestroyWindow do niszczenia obiektu C++ Windows zamiast delete operatora.

Postępuj zgodnie z wytycznymi, w tym temacie, masz kilka problemów oczyszczania.Te problemy mogą wynikać z problemów, takich jak Zapominanie o delete/zwolnienia pamięci C++, zapominając zwolnić zasoby systemowe, takie jak HWNDs lub zwalnianie obiektów zbyt wiele razy.

Problem

Każdy obiekt systemu windows (obiekt klasy pochodzące z CWnd) reprezentuje zarówno obiekt C++ i HWND.Obiekty C++ są przydzielane w sterty aplikacji i HWNDs są przydzielane w zasoby systemowe przez Menedżera okien.Ponieważ zniszczenie obiektu window na wiele sposobów, oferujemy musi zestaw reguł, które uniemożliwiają systemu przecieki pamięci lub zasobów.Zasady te muszą również uniemożliwić obiektów i uchwyty Windows zniszczeniu więcej niż jeden raz.

Niszczenie systemu Windows

Oto dwa sposoby dozwolone zniszczyć obiekt systemu Windows:

  • Wywołanie CWnd::DestroyWindow lub Windows API DestroyWindow.

  • Jawnie usuwanie z delete operatora.

Pierwszy przypadek jest zdecydowanie najbardziej typowe.Ten przypadek dotyczy, nawet jeżeli kod nie wywoływać DestroyWindow bezpośrednio.Gdy użytkownik zamyka bezpośrednio w oknie ramki, Akcja ta generuje WM_CLOSE wiadomości i odpowiedzi domyślnej na ten komunikat jest wywołanie DestroyWindow. gdy okno nadrzędne jest niszczony, system Windows wywołuje DestroyWindow dla wszystkich jego elementów podrzędnych.

Drugim przypadku, korzystanie z delete operatora obiektów systemu Windows powinien być rzadko.Następujące są, w niektórych przypadkach, gdy za pomocą delete jest poprawny wybór.

Oczyszczanie automatyczne z CWnd::PostNcDestroy

Gdy system niszczy okno systemu Windows, jest ostatnią wiadomością Windows wysyłane do okna WM_NCDESTROY.Domyślnie CWnd obsługi dla tej wiadomości jest CWnd::OnNcDestroy.OnNcDestroyOdłączanie będzie HWND z C++ obiektu i wywołać funkcję wirtualną PostNcDestroy.Niektóre klasy zastępują tej funkcji, aby usunąć obiekt C++.

Domyślne wykonania CWnd::PostNcDestroy nie wykonuje żadnej operacji, która jest odpowiednia dla obiektów okno, które są przydzielone ramki stosu lub osadzone w innych obiektów.Nie jest to właściwe dla obiektów okno, które mają być przydzielone na stercie bez żadnych innych obiektów.Innymi słowy nie jest właściwe dla obiektów okno, które nie są osadzone w innych obiektów C++.

Zastąpienie tych klas, które są przeznaczone do przydzielenia samodzielnie na stercie PostNcDestroy metody do wykonywania delete this.Ta instrukcja zwolni pamięci, wszelkie skojarzone z obiektem C++.Chociaż domyślne CWnd wywołania destruktora DestroyWindow Jeśli m_hWnd jest inne niż NULL, nie doprowadzi do nieskończonej rekursji, ponieważ dojście będzie odłączony i NULL podczas fazy oczyszczania.

[!UWAGA]

Zwykle wywołuje CWnd::PostNcDestroy po przetwarza Windows WM_NCDESTROY wiadomości oraz HWND i obiekt window C++ są już podłączone.System będzie również wywołać CWnd::PostNcDestroy w realizacji większość CWnd::Create wymaga, jeśli wystąpi awaria.Zasady automatycznego oczyszczania są opisane w dalszej części tego tematu.

Klasy Oczyszczanie automatyczne

Następujące klasy nie są przeznaczone dla automatycznego oczyszczania.Zazwyczaj są osadzone w innych obiektów C++ lub stosu:

  • Wszystkich standardowych formantów systemu Windows (CStatic, CEdit, CListBoxi tak dalej).

  • Wszelkie okien podrzędnych pochodzi bezpośrednio z CWnd (na przykład niestandardowych formantów).

  • Windows rozdzielacza (CSplitterWnd).

  • Domyślnie paski kontroli (pochodną klasy CControlBar, zobacz technicznej 31 Uwaga umożliwiających automatyczne usuwanie obiektów pasek sterowania).

  • Okna dialogowe (CDialog) przeznaczone dla modalnych okien dialogowych w ramce stosu.

  • Wszystkie standardowe okna dialogowe z wyjątkiem CFindReplaceDialog.

  • Okna dialogowe domyślne, utworzony przez ClassWizard.

Następujące klasy są przeznaczone dla automatycznego oczyszczania.Są one zazwyczaj przydzielane przez same na stercie:

  • Główna ramka windows (pochodzące bezpośrednio lub pośrednio z CFrameWnd).

  • Wyświetlanie okien (pochodzące bezpośrednio lub pośrednio z CView).

Jeśli chcesz przerwać zasady te należy zastąpić PostNcDestroy metoda w klasie pochodnej.Aby dodać klasę automatyczne oczyszczanie, wywołanie klasy podstawowej, a następnie wykonaj delete this.Aby usunąć klasę automatyczne oczyszczanie, wywołać CWnd::PostNcDestroy bezpośrednio, zamiast PostNcDestroy metoda bezpośrednia klasa podstawowa.

Najczęściej zmiana zachowania Oczyszczanie automatyczne jest utworzenie niemodalne okno dialogowe, która może być alokowana na stercie.

Gdy do wywołania delete

Firma Microsoft zaleca, aby wywołać DestroyWindow do niszczenia obiektu Windows, metoda C++ lub globalnym DestroyWindow interfejsu API.

Nie wywołuj globalnym DestroyWindow API, aby zniszczyć okno potomne MDI.Należy użyć metody wirtualnego CWnd::DestroyWindow zamiast.

Dla okna C++ obiektów, nie wykonuj automatyczne oczyszczanie, za pomocą delete operator może spowodować przeciek pamięci podczas próby wywołania DestroyWindow w CWnd::~CWnd destruktor, jeśli VTBL nie wskazuje klasy pochodnej poprawnie.Dzieje się tak, ponieważ system nie może odnaleźć odpowiednie metody do wywołania zniszczenia.Za pomocą DestroyWindow zamiast delete pozwala uniknąć tych problemów.Ponieważ może to być błąd subtelne, kompilacji w trybie debugowania generują następujące ostrzeżenie są zagrożone.

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

W odniesieniu do obiektów C++, Windows, które należy wykonywać oczyszczanie automatyczne, należy wywołać DestroyWindow.Jeśli korzystasz z delete operatora bezpośrednio, program przydzielania diagnostyki pamięci biblioteki MFC powiadomi że dwa razy są zwalniania pamięci.Dwa wystąpienia są Twoje pierwsze wywołanie jawne i pośrednich wywołanie delete this w realizacji Oczyszczanie automatyczne PostNcDestroy.

Po wywołaniu DestroyWindow na obiekcie nie Oczyszczanie automatyczne, obiekt C++ nadal będzie się wokół, ale m_hWnd będzie mieć wartość NULL.Po wywołaniu DestroyWindow na obiekt automatycznego oczyszczania obiektów C++ będzie zniknął, zwolniona przez operatora delete C++ w realizacji Oczyszczanie automatyczne PostNcDestroy.

Zobacz też

Inne zasoby

Uwagi techniczne przez liczbę

Uwagi techniczne według kategorii