TN017: Löschen von Fensterobjekten
Dieser Hinweis wird die Verwendung der CWnd::PostNcDestroy-Methode.Verwenden Sie diese Methode, wenn Sie benutzerdefinierte Zuordnung von CWnd abgeleitete Objekte durchführen möchten.Dieser Hinweis wird erläutert, warum Sie auch verwendet werden, um CWnd::DestroyWindow Ein Objekt delete Windows C++-Compiler anstelle des Operators zu zerstören.
Wenn Sie die Richtlinien in diesem Thema folgen, können Sie die Bereinigung wenige Probleme.Diese Probleme können sich von Problemen wie Vergessen C++-Arbeitsspeicher deaktivieren/löschen, Vergessen, Systemressourcen wie HWND s freizugeben oder Objekte zu oft freigeben.
Das Problem
Jedes Fenster Objekt Objekt einer Klasse (abgeleitet von CWnd) stellt im C-Format HWND und C++-Compiler Objekt dar.C++-Objekte werden im Heap der Anwendung zugeordnet und HWND s sind in Systemressourcen aus der Fenster-Manager zugeordnet.Da es mehrere Möglichkeiten gibt, ein Window-Objekt zu zerstören, müssen wir einen Satz von Regeln schaffen, die Systemressource oder Speicherverluste verhindern.Diese Regeln müssen ebenfalls verhindern, dass Objekte und Windows-Handles mehr als einmal gelöscht.
Windows zerstören
Im Folgenden werden die beiden zulässigen Möglichkeiten, ein Windows-Objekt zu zerstören:
CWnd::DestroyWindow oder Windows-APIs DestroyWindow aufrufen.
Explizit, mit dem Löschen der delete-Operator.
Im ersten Fall handelt es sich bei weitem die meisten allgemeinen.In diesem Fall gilt auch, wenn der Code nicht DestroyWindow direkt aufruft.Wenn der Benutzer direkt ein Rahmenfenster schließt, wird diese Aktion die WM_CLOSE Fehlermeldung angezeigt und die Antwort auf diese Nachricht ist, DestroyWindow., wenn ein übergeordnetes Fenster zerstört wird, Windows aufzurufen aufruft DestroyWindow für alle untergeordneten Elemente.
Im zweiten Fall die Verwendung des Operators auf delete Windows-Objekten, sollte selten sein.Im Folgenden werden einige Fälle, in denen delete, ist die richtige Wahl.
Automatisches Bereinigung mit CWnd::PostNcDestroy
Wenn das System ein Windows-Fenster zerstört, ist die letzte Windows-Meldung, die an das Fenster gesendet wird, WM_NCDESTROY.Der Standardwert CWnd-Handler für diese Meldung lautet CWnd::OnNcDestroy.OnNcDestroy trennt HWND vom C++-Objekt und ruft die virtuelle Funktion PostNcDestroy an.Einige Klassen überschreiben diese Funktion, um das C++-Objekt zu löschen.
Die Standardimplementierung von CWnd::PostNcDestroy führt keine Aktion aus, die für Fensterobjekte geeignet ist, die auf dem Stapelrahmen zugeordnet sind oder anderen Objekten eingebettet.Dies ist nicht für Fensterobjekte geeignet, die auf dem Heap ohne andere Objekte zugeordnet werden soll.Das bedeutet, dass es nicht für Fensterobjekte, die nicht in anderen C++-Objekten eingebettet sind.
Diese Klassen, die auf dem Heap allein Überschreibung zugeordnet werden die PostNcDestroy-Methode, um delete this auszuführen.Diese Anweisung gibt den Arbeitsspeicher frei, der mit dem C++-Objekt zugeordnet ist.Obwohl der Standardwert CWndDestroyWindow Destruktor aufgerufen wird, wenn m_hWnd ungleich null ist, führt dies nicht zu unendliche Rekursion, da das Handle getrennt und während der Bereinigung phase NULL ist.
Hinweis |
---|
Das System ruft normalerweise CWnd::PostNcDestroy an, nachdem es die Meldung verarbeitet und WM_NCDESTROY Windows HWND und das C++-Fensterobjekt nicht mehr miteinander verbunden sind.Das System ruft außerdem CWnd::PostNcDestroy in der Implementierung der meisten CWnd::Create Aufrufe an, wenn Fehler auftritt.Die Regeln für die automatische Bereinigung werden weiter unten in diesem Thema beschrieben. |
Automatische Cleanup-Klassen
Die folgenden Klassen sind nicht für die automatische Bereinigung vorgesehen.Sie werden in der Regel in anderen C++-Objekten oder auf dem Stapel enthalten:
Alle Standardwert windows-steuerelemente (CStatic, CEdit, CListBox usw.).
Alle untergeordneten Fenster abgeleitet CWnd direkt aus (z. B. benutzerdefinierte Steuerelement).
Splitterfenster (CSplitterWnd).
standardmäßigen Steuerleisten (Klassen, die von CControlBar abgeleitet sind, finden Technischer Hinweis 31 zum Aktivieren der automatischen DELETE für Steuerleisten Objekte).
Dialogfelder (CDialog) vorgesehen für modale Dialogfelder auf dem Stapelrahmen.
Alle CFindReplaceDialog stellen Standarddialogfelder aus.
Die Dialogfelder ClassWizard erstellt wurden.
Die folgenden Klassen sind für die automatische Bereinigung vorgesehen.Sie werden in der Regel auch auf dem Heap reserviert:
Hauptrahmenfenster (abgeleitet von CFrameWnd direkt oder indirekt).
Ansichtsfenster direkt oder indirekt (abgeleitet von CView).
Wenn Sie diese Regeln unterbrechen möchten, müssen Sie die PostNcDestroy-Methode in der abgeleiteten Klasse überschrieben werden.Um die automatische Bereinigung der Klasse hinzu, rufen Sie die Basisklasse her, und führen Sie dann delete this.Um die automatische Bereinigung von der Klasse zu entfernen, rufen Sie CWnd::PostNcDestroy direkt anstelle der direkten PostNcDestroy-Methode der Basisklasse auf.
Der häufigste Verwendung von Ändern des automatischen Bereinigen ist, kann ein nicht modales Dialogfeld, das auf dem Heap zugeordnet werden kann.
Wann Delete aufrufen
Es wird empfohlen, DestroyWindow aufrufen, um ein Windows-Objekt zu zerstören, die C++-Methode oder das globale DestroyWindow API.
Rufen Sie nicht die globale DestroyWindow APIs an, die ein untergeordnetes MDI-Fenster zu zerstören.Sie sollten die virtuelle Methode CWnd::DestroyWindow-Version verwenden.
Für C++-Fensterobjekte, die keine automatische Bereinigung ausführen, mit dem delete-Operators kann einen Speicherverlust führen, wenn Sie versuchen, DestroyWindow im CWnd::~CWnd Destruktor aufgerufen wird, wenn das VTBL nicht ordnungsgemäß in die abgeleitete Klasse veranschaulicht.Dies tritt auf, da das System das geeignete Methode zerstört nicht finden kann, die aufgerufen werden soll.Verwenden DestroyWindow anstelle delete vermeidet diese Probleme.Da dieser ein subtiler Fehler sein kann, generiert die Kompilierung im Debugmodus die folgende Warnung, wenn Sie ein Risiko darstellen.
Warning: calling DestroyWindow in CWnd::~CWnd
OnDestroy or PostNcDestroy in derived class will not be called
Bei Windows C++ Objekte, die automatische Bereinigung ausführen, müssen Sie DestroyWindow aufrufen.Wenn Sie den Operator delete direkt verwenden, benachrichtigt die Diagnose Speicherbelegungsfunktion MFC Sie, dass Sie zweimal Arbeitsspeicher freigeben.Die beiden Instanzen sind expliziten Aufruf des ersten und indirekten Aufruf von delete this in der automatische Bereinigung Implementierung von PostNcDestroy.
Nach dem DestroyWindow auf einem Nicht-AUTO Bereinigung Objekt aufgerufen hat, ist das C++-Objekt ungefähr, aber noch m_hWnd ist NULL.Nachdem die auf einem DestroyWindow automatische Bereinigung Objekt aufgerufen hat, wird das C++-Objekt gegangen freigegeben, durch den C++-delet-Operator in der automatische Bereinigung Implementierung von PostNcDestroy.