2009-06-03 3 views
7
// CMyDialog inherits from CDialog 
void CMyFrame::OnBnClickedCreate() 
{ 
    CMyDialog* dlg = new CMyDialog(); 
    dlg->Create(IDD_MYDIALOG, m_thisFrame); 
    dlg->ShowWindow(SW_SHOW); 
} 

Ich bin ziemlich sicher, dass dies leckt. Was ich wirklich frage ist: Gibt es irgendeine "Magie" in MFC, die Dialogbereinigung durchführt, wenn der Dialog zerstört wird. Wie würde es funktionieren, wenn dlg kein Pointer wäre, sondern auf dem Stack deklariert würde - würde der Destruktor das Fenster nicht zerstören, wenn dlg den Gültigkeitsbereich verlässt?Ist dies ein Speicherleck in MFC

Antwort

12

Ja, ist es Speicherleck in Ihrem Fall, aber Sie können durch die Nutzung der überwiegenden PostNcDestroy Speicherleck in Fällen, in denen nicht modales Dialogfeld auf dem Heap zugewiesen vermeiden.

Dialoge sind nicht für Auto-Cleanup (wo Mainframe-Fenster, View-Fenster sind) entwickelt. Wenn Sie die automatische Bereinigung für Dialoge bereitstellen möchten, müssen Sie die Elementfunktion PostNcDestroy in Ihrer abgeleiteten Klasse überschreiben. Um eine automatische Bereinigung zu Ihrer Klasse hinzuzufügen, rufen Sie Ihre Basisklasse auf und führen Sie dann eine delete this aus. Um die automatische Bereinigung aus Ihrer Klasse zu entfernen, rufen Sie CWnd::PostNcDestroy direkt anstelle der PostNcDestroy Mitglied in Ihrer direkten Basisklasse.

void MyDialog::PostNcDestroy() 
{ 

    CDialog::PostNcDestroy(); 
    delete this; 
} 

Wie das funktioniert (von MSDN):

Wenn ein Windows-Fenster zerstört, die letzte Windows-Nachricht an das gesendet Fenster ist WM_NCDESTROY. Der CWnd-Standardhandler für diese Nachricht (CWnd :: OnNcDestroy) wird die HWND von dem C++ - Objekt trennen und die virtuelle -Funktion PostNcDestroy aufrufen. Einige Klassen überschreiben diese Funktion, um das C++ - Objekt zu löschen.

"delete this" wird alle C++ Speicher freigeben, die dem C++ - Objekt zugeordnet sind. Auch wenn der Standard CWnd destructor Anrufe Destroy wenn m_hWnd Nicht-NULL ist, führt dies nicht zu unendlicher Rekursion, da der Griff während der Bereinigungsphase abgelöst und NULL werden.

Sie können auch für weitere Details auf MSDN (Destroying Window Objects) verweisen.

Hinweis:

Die für modalen Dialog arbeitet, die auf den Haufen zugeordnet werden können.

3

Ja, das ist ein Leck. Und ja, das Fenster würde zerstört werden, wenn das Objekt stack-allokiert wäre. Die Verwendung von Dialogen als stack-allokierte Objekte ist typisch für modale Dialoge - Sie rufen eine Methode auf, um einen Dialog als modales Fenster anzuzeigen, und diese Methode kehrt nur zurück, wenn der Dialog geschlossen und das Objekt danach zerstört wird.

+0

Danke. Ich habe vergessen zu sagen, dass dies für einen modeless Dialog ist. Ich gehe davon aus, dass in diesem Fall das Dialogobjekt eine Membervariable sein muss, damit es im Frames-Destruktor zerstört/entfernt werden kann. – Richard

2

Wenn Sie manuell Create auf einen Dialog aufrufen, müssen Sie manuell Destroy es auch.
Bei Verwendung von DoModal() ist dies nicht erforderlich.

Von MSDN:

Verwenden Sie die CWnd :: Destroy Funktion ein Dialogfeld mit der Funktion Anlegen erstellt zu zerstören.