¿Es esta una pérdida de memoria en MFC?

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

Estoy bastante seguro de que esto gotea. Lo que realmente pregunto es: ¿hay alguna “magia” en MFC que limpie el diálogo cuando se destruye el diálogo? ¿Cómo funcionaría si dlg no fuera un puntero pero se declarara en la stack? ¿No destruiría la ventana el destructor cuando dlg se salga del scope?

Sí, se trata de una pérdida de memoria en su caso, pero puede evitar la pérdida de memoria en los casos en que el diálogo no se asigna en el montón haciendo uso de la anulación de PostNcDestroy .

Los cuadros de diálogo no están diseñados para la limpieza automática (donde las ventanas de marco principal, las ventanas de vista). En caso de que desee proporcionar la limpieza automática de los cuadros de diálogo, debe anular la función miembro PostNcDestroy en su clase derivada. Para agregar limpieza automática a su clase, llame a su clase base y luego delete this . Para eliminar la limpieza automática de su clase, llame a CWnd::PostNcDestroy directamente en lugar del miembro PostNcDestroy en su clase base directa.

 void MyDialog::PostNcDestroy() { CDialog::PostNcDestroy(); delete this; } 

Cómo funciona esto (desde MSDN):

Al destruir una ventana de Windows, el último mensaje de Windows enviado a la ventana es WM_NCDESTROY. El controlador de CWnd predeterminado para ese mensaje (CWnd :: OnNcDestroy) separará el HWND del objeto C ++ y llamará a la función virtual PostNcDestroy. Algunas clases anulan esta función para eliminar el objeto C ++.

“eliminar esto” liberará cualquier memoria C ++ asociada con el objeto C ++. Aunque el destructor CWnd predeterminado llama a DestroyWindow si m_hWnd no es NULL, esto no lleva a una recursión infinita ya que el identificador se separará y NULL durante la fase de limpieza.

También puede consultar MSDN ( Destrucción de objetos de ventana ) para obtener más detalles.

Nota:

Esto funciona para el diálogo sin modelo que se puede asignar en el montón .

Sí, eso es una fuga. Y sí, la ventana se destruiría si el objeto estuviera asignado a la stack. El uso de cuadros de diálogo como objetos asignados a la stack es típico de los cuadros de diálogo modales: se llama un método para mostrar un cuadro de diálogo como una ventana modal y ese método solo se devuelve cuando el cuadro de diálogo se cierra y el objeto se destruye después de eso.

Si llama manualmente a Create en un diálogo, también tiene que Destroy manualmente.
Cuando se usa DoModal() esto no es necesario.

Desde MSDN :

Use la función CWnd :: DestroyWindow para destruir un cuadro de diálogo creado por la función Crear.