Это утечка памяти в MFC - PullRequest
8 голосов
/ 03 июня 2009
// CMyDialog inherits from CDialog 
void CMyFrame::OnBnClickedCreate()
{
    CMyDialog* dlg = new CMyDialog();
    dlg->Create( IDD_MYDIALOG, m_thisFrame );
    dlg->ShowWindow( SW_SHOW );
}

Я почти уверен, что это утечка. Что я действительно спрашиваю: есть ли в MFC «магия», которая делает очистку диалога, когда диалог уничтожается. Как это будет работать, если dlg не будет указателем, а объявлен в стеке - не разрушит ли деструктор окно, когда dlg выйдет из области видимости.

Ответы [ 3 ]

16 голосов
/ 03 июня 2009

Да, это утечка памяти в вашем случае, но вы можете избежать утечки памяти в случаях, когда немодальное диалоговое окно выделено в куче, используя переопределение PostNcDestroy.

Диалоги не предназначены для автоматической очистки (где окна основного кадра, окна просмотра). Если вы хотите обеспечить автоматическую очистку для диалогов, вы должны переопределить функцию-член PostNcDestroy в своем производном классе. Чтобы добавить автоматическую очистку в ваш класс, позвоните в базовый класс, а затем выполните delete this. Чтобы удалить автоочистку из вашего класса, вызовите CWnd::PostNcDestroy напрямую вместо PostNcDestroy члена вашего прямого базового класса.

void MyDialog::PostNcDestroy() 
{

    CDialog::PostNcDestroy();
    delete this;
}

Как это работает (из MSDN):

При уничтожении окна Windows последнее сообщение Windows, отправленное окно является WM_NCDESTROY. По умолчанию CWnd обработчик для этого сообщения (CWnd :: OnNcDestroy) отсоединит HWND из объекта C ++ и вызвать виртуальная функция PostNcDestroy. Немного классы переопределяют эту функцию на удалить объект C ++.

"удалить это" освободит любой C ++ память, связанная с объектом C ++. Хотя по умолчанию CWnd деструктор вызывает DestroyWindow, если m_hWnd не NULL, это не приводит до бесконечной рекурсии, так как ручка будет отсоединен и NULL во время фаза очистки.

Вы также можете обратиться к MSDN ( Уничтожение оконных объектов ) для получения дополнительной информации.

Примечание:

Это работает для немодального диалога, который можно выделить в куче .

4 голосов
/ 03 июня 2009

Да, это утечка. И да, окно будет уничтожено, если объект будет размещен в стеке. Использование диалогов в качестве объектов, размещенных в стеке, типично для модальных диалогов - вы вызываете метод для отображения диалога в качестве модального окна, и этот метод возвращается только тогда, когда диалоговое окно закрыто и после этого объект уничтожается.

3 голосов
/ 03 июня 2009

Если вы вручную вызываете Create в диалоговом окне, вы должны вручную Destroy также.
При использовании DoModal() в этом нет необходимости.

С MSDN :

Используйте функцию CWnd :: DestroyWindow уничтожить диалоговое окно, созданное Создать функцию.

...