TN017: Eliminare gli oggetti Window
Questa nota viene descritto l'utilizzo del metodo di CWnd::PostNcDestroy .Utilizzare questo metodo se si desidera effettuare l'allocazione personalizzata di CWndoggetti derivati da.Questa nota viene inoltre spiegato perché è necessario utilizzare CWnd::DestroyWindow per eliminare le finestre C++ definirle anziché l'operatore di delete .
Seguendo le istruzioni riportate in questo argomento, saranno poche problemi di pulizia.Questi problemi possono derivare da problemi come si dimentichi di eliminare/memoria C++, si dimentichi di liberare le risorse di sistema come HWNDoggetti, o versione degli oggetti troppe volte.
Il problema
Ogni oggetto di windows (oggetto di una classe derivata da CWnd) per entrambi i oggetto C++ e HWND.Gli oggetti C++ vengono allocati nell'heap dell'applicazione e HWNDgli oggetti è allocato alle risorse di sistema dall'amministratore di finestra.Poiché esistono diversi modi per eliminare un oggetto finestra di, è necessario fornire un set di regole che impediscono la risorsa di sistema o le perdite di memoria.Queste regole devono possibile evitare gli oggetti e gli handle di windows da distruggere più di uno volta.
Eliminare le finestre
Di seguito sono indicate due modalità consentite eliminare un oggetto di windows:
Chiamare CWnd::DestroyWindow o l'API Windows DestroyWindow.
In modo esplicito eliminando con l'operatore di delete .
Il primo caso è di gran lunga la più comune.In questo caso si applica anche se il codice non chiama direttamente DestroyWindow .Quando l'utente direttamente chiude una finestra cornice, questa azione viene generato il messaggio di WM_CLOSE e la risposta predefinita a questo messaggio è chiamare **DestroyWindow.**quando una finestra padre viene eliminato, windows chiama DestroyWindow per tutti i relativi elementi figlio.
Il secondo caso, l'utilizzo dell'operatore di delete sulle finestre oggetti, deve essere concessi.Di seguito sono riportati alcuni casi utilizzando delete costituiscono la scelta corretta.
Pulizia automatica con CWnd::PostNcDestroy
Quando il sistema elimina una finestra di windows, l'ultimo messaggio di windows inviato alla finestra è WM_NCDESTROY.Il gestore predefinito di CWnd per il messaggio viene CWnd::OnNcDestroy.OnNcDestroy in HWND dall'oggetto C++ e chiamerà la funzione virtuale PostNcDestroy.Alcune classi eseguono l'override della funzione per eliminare l'oggetto C++.
L'implementazione predefinita di CWnd::PostNcDestroy non esegue alcuna operazione, che sia appropriato per gli oggetti della finestra allocati nello stack frame o sono incorporati in altri oggetti.Questa operazione non è adatta agli oggetti della finestra progettati per essere allocati nell'heap senza altri oggetti.Ovvero non è appropriato per gli oggetti della finestra che non sono incorporati in altri oggetti C++.
Tali classi progettate per essere allocati da solo su un heap il metodo di PostNcDestroy per eseguire delete this.Questa istruzione in caso di tutta la memoria associata con l'oggetto C++.Anche se il distruttore di CWnd di impostazione predefinita chiama DestroyWindow se m_hWnd non è Null, questo non è la ricorsione infinita perché un handle verranno rimosse e NULL durante la fase di pulizia.
[!NOTA]
Il sistema in genere chiama CWnd::PostNcDestroy dopo l'elaborazione del messaggio di WM_NCDESTROY di windows e HWND e l'oggetto della finestra C++ non sono più connesso.Il sistema anche chiamerà CWnd::PostNcDestroy implementazione della maggior parte delle chiamate di CWnd::Create se si verificherà questo errore.Le regole automatiche di pulitura sono descritte più avanti in questo argomento.
Classi automatiche di pulizia
Le classi seguenti non sono progettate per la auto-pulizia.In genere vengono incorporate in altri oggetti C++ o nello stack:
Tutti i controlli Windows standard (CStatic, CEdit, CListBox, e così via).
Tutte le finestre figlio derivate direttamente da CWnd , ad esempio controlli personalizzati).
Finestre con separatore (CSplitterWnd).
Barre di controllo predefinite (classi derivate da CControlBar, vedere nota tecnica 31 per abilitare la auto-cancellazione per gli oggetti della barra di controllo).
Finestre di dialogo (CDialog) progettate per le finestre di dialogo modali sullo stack frame.
Tutte le finestre di dialogo standard esclusi CFindReplaceDialog.
Le finestre di dialogo predefinite create da ClassWizard.
Le classi seguenti sono progettate per la auto-pulizia.In genere vengono allocate da sole nell'heap:
Applicazioni utilizzano principali (derivate direttamente o indirettamente da CFrameWnd).
Finestre di visualizzazione (derivate direttamente o indirettamente da CView).
Se si desidera violare queste procedure, è necessario eseguire l'override del metodo di PostNcDestroy nella classe derivata.Per aggiungere la auto-pulizia alla classe, chiamare la classe di base e quindi fare delete this.Per rimuovere la auto-pulizia dalla classe, chiamare CWnd::PostNcDestroy direttamente anziché il metodo di PostNcDestroy della classe di base diretta.
La maggior parte di utilizzo comune di modifica del comportamento automatico di pulitura viene creata una finestra di dialogo non modale che può essere allocata nell'heap.
Quando si chiama eliminazione
È consigliabile chiamare DestroyWindow per eliminare un oggetto di windows, il metodo C++ o DestroyWindow globale API.
Non chiamare DestroyWindow globale API per eliminare una finestra figlio MDI.È necessario utilizzare il metodo virtuale CWnd::DestroyWindow anziché.
Per gli oggetti Window C++ che non eseguono la auto-pulizia, utilizzando l'operatore di delete può provocare una perdita di memoria quando si tenta di chiamare DestroyWindow nel distruttore di CWnd::~CWnd se il VTBL non indica correttamente la classe derivata.Ciò accade perché il sistema non è in grado di trovare l'oggetto appropriato elimina il metodo da chiamare.Utilizzando DestroyWindow anziché delete evitare questi problemi.Poiché questo può essere un errore sottile, compilare in modalità di debug genererà il seguente avviso se si è al rischio.
Warning: calling DestroyWindow in CWnd::~CWnd
OnDestroy or PostNcDestroy in derived class will not be called
Nel caso di oggetti di windows C++ che eseguono la auto-pulizia, è necessario chiamare DestroyWindow.Se si utilizzano direttamente l'operatore di delete , l'allocatore di memoria diagnostico MFC visualizzerà una notifica che si liberando memoria due volte.Le due occorrenze sono la prima chiamata esplicita e la chiamata indiretta a delete this nell'implementazione di auto-pulizia di PostNcDestroy.
Dopo avere chiamato DestroyWindow su un oggetto di non autoidentificatore pulizia, l'oggetto C++ sarà ancora in, ma m_hWnd sarà NULL.Dopo avere chiamato DestroyWindow su un oggetto di auto-pulizia, l'oggetto C++ sarà più disponibile, liberato dall'operatore delete C++ nell'implementazione di auto-pulizia di PostNcDestroy.