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

Je suis assez sûr que cela fuit. Ce que je demande vraiment, c'est: y at-il une "magie" dans MFC qui nettoie les dialogues quand le dialogue est détruit. Comment cela fonctionnerait-il si dlg n'était pas un pointeur mais déclaré sur la pile - le destructeur ne détruirait-il pas la fenêtre quand dlg sort de la portée.Est-ce une fuite de mémoire dans MFC

Répondre

12

Oui, il est fuite de mémoire dans votre cas, mais vous pouvez éviter la fuite de mémoire dans les cas où de dialogue modales attribués sur le tas en faisant usage de passer outre PostNcDestroy.

Dialogs ne sont pas conçus pour l'auto-nettoyage (où les fenêtres de cadre principal, fenêtres View sont). Si vous souhaitez fournir le nettoyage automatique pour les boîtes de dialogue, vous devez remplacer la fonction membre PostNcDestroy de votre classe dérivée. Pour ajouter un nettoyage automatique à votre classe, appelez votre classe de base, puis faites un delete this. Pour supprimer le nettoyage automatique de votre classe, appelez le CWnd::PostNcDestroy directement au lieu du membre PostNcDestroy dans votre classe de base directe.

void MyDialog::PostNcDestroy() 
{ 

    CDialog::PostNcDestroy(); 
    delete this; 
} 

Comment cela fonctionne (à partir de MSDN):

Lors de la destruction d'une fenêtre Windows, le dernier message de Windows envoyé à la fenêtre est WM_NCDESTROY. Le gestionnaire CWnd par défaut pour ce message (CWnd :: OnNcDestroy) va détacher le HWND de l'objet C++ et appeler la fonction virtuelle PostNcDestroy. Certaines classes remplacent cette fonction pour supprimer l'objet C++.

« supprimer cette » libérera une mémoire C++ associée à l'objet C de. Même si les appels par défaut CWnd destructor DestroyWindow si m_hWnd est non NULL, cela ne conduit pas à récursion infinie puisque la poignée sera détaché et NULL lors de la phase de nettoyage .

Vous pouvez également vous référer à MSDN (Destroying Window Objects) pour plus de détails.

Note:

Cela fonctionne pour dialogue modales qui peut être alloué sur le tas .

3

Oui, c'est une fuite. Et oui, la fenêtre serait détruite si l'objet était alloué en pile. L'utilisation de boîtes de dialogue comme objets alloués par pile est typique pour les boîtes de dialogue modales - vous appelez une méthode pour afficher une boîte de dialogue comme fenêtre modale et cette méthode ne revient que lorsque la boîte de dialogue est fermée et l'objet détruit.

+0

Merci. J'ai oublié de dire que c'est pour une boîte de dialogue Modeless. Je suppose que dans ce cas pour le nettoyage, l'objet de dialogue doit être une variable membre - donc il peut être détruit/désaffecté dans le destructeur d'images. – Richard

2

Si vous appelez manuellement Create sur une boîte de dialogue, vous devez manuellement Destroy aussi.
Lors de l'utilisation DoModal() ce n'est pas nécessaire.

De MSDN:

Utilisez la fonction CWnd :: DestroyWindow pour détruire une boîte de dialogue créée par la fonction Créer.