TN017: Destruir janela objetos
Esta anotação descreve o uso de CWnd::PostNcDestroy método.Use este método se você deseja fazer alocação personalizada de CWnd-derivado de objetos.Esta nota também explica por que você deve usar CWnd::DestroyWindow para destruir um objeto C++ Windows em vez do delete operador.
Se você seguir as diretrizes neste tópico, você terá alguns problemas de limpeza.Esses problemas podem resultar de problemas como esquecer de excluir/liberar memória do C++, esquecer de liberar recursos do sistema como HWNDs ou liberando objetos muitas vezes.
O problema
Cada objeto do windows (objeto de uma classe derivada de CWnd) representa um objeto de C++ e um HWND.Objetos C++ são alocados no heap do aplicativo e HWNDs recursos de sistema são alocados pelo Gerenciador de janela.Como existem várias maneiras de destruir um objeto de janela, devemos fornecer um conjunto de regras que impedem que o sistema de vazamentos de memória ou recursos.Essas regras também devem evitar Windows controla e objetos sejam destruídos mais de uma vez.
Destruindo o Windows
A seguir estão maneiras permitidas para destruir um objeto do Windows:
Chamando CWnd::DestroyWindow ou a API do Windows DestroyWindow.
Excluindo explicitamente com o delete operador.
O primeiro caso é de longe o mais comum.Neste caso se aplica mesmo se seu código não chama DestroyWindow diretamente.Quando o usuário diretamente fecha uma janela do quadro, essa ação gera a WM_CLOSE mensagem e a resposta padrão para essa mensagem é chamar DestroyWindow. quando uma janela pai é destruída, o Windows chama DestroyWindow para todos os seus filhos.
O segundo caso, o uso da delete operador de objetos do Windows devem ser raros.A seguir estão alguns casos onde usar delete a opção correta.
Limpeza automática com CWnd::PostNcDestroy
Quando o sistema destrói uma janela do Windows, a última mensagem do Windows enviada para a janela é WM_NCDESTROY.O padrão CWnd manipulador para a mensagem é CWnd::OnNcDestroy.OnNcDestroyirá desanexar o HWND C++ de objeto e chamar a função virtual PostNcDestroy.Algumas classes substituem esta função para excluir o objeto C++.
A implementação padrão de CWnd::PostNcDestroy não faz nada, que é apropriado para objetos de janela que são alocados no quadro de pilha ou incorporados em outros objetos.Não é apropriado para objetos de janela são projetados para ser alocada no heap sem outros objetos.Em outras palavras, não é apropriado para objetos de janela que não são incorporados em outros objetos do C++.
Essas classes são projetadas para ser alocado sozinho no heap substituem o PostNcDestroy método para executar um delete this.Esta instrução será livre qualquer memória associada ao objeto C++.Embora o padrão CWnd destruidor chamadas DestroyWindow se m_hWnd é nula, isso não levar a recursão infinita porque o identificador será desanexado e nulo durante a fase de limpeza.
Observação |
---|
O sistema normalmente chama CWnd::PostNcDestroy depois que o Windows processa WM_NCDESTROY mensagem e o HWND e o objeto de janela C++ não está mais conectado.O sistema também irá chamar CWnd::PostNcDestroy na implementação das mais CWnd::Create chama se ocorrer falha.As regras de limpeza automática são descritas posteriormente neste tópico. |
Classes de limpeza automática
As seguintes classes não são projetadas para a limpeza automática.Eles geralmente são incorporados em outros objetos C++ ou na pilha:
Todos os controles padrão do Windows (CStatic, CEdit, CListBoxe assim por diante).
Todas as janelas filho derivada diretamente de CWnd (por exemplo, controles personalizados).
Windows divisor (CSplitterWnd).
Padrão de barras de controle (classes derivadas de CControlBar, consulte técnico anotação 31 para ativar a exclusão automática para objetos de barra de controle).
Caixas de diálogo (CDialog) projetado para caixas de diálogo modais no quadro de pilha.
O padrão todos os diálogos exceto CFindReplaceDialog.
As caixas de diálogo padrão criadas por ClassWizard.
As classes a seguir destinam-se a limpeza automática.Eles geralmente são alocados por si na pilha:
Windows de quadro principal (derivada direta ou indiretamente de CFrameWnd).
Exibir windows (derivado direta ou indiretamente de CView).
Se você deseja quebrar essas regras, você deve substituir o PostNcDestroy método na sua classe derivada.Para adicionar a limpeza automática para sua classe, chamada de classe base e faça um delete this.Para remover a limpeza automática de sua classe, chamada CWnd::PostNcDestroy diretamente em vez do PostNcDestroy método de sua classe base direta.
O uso mais comum de alterar o comportamento de limpeza automática é criar uma caixa de diálogo sem janela restrita que pode ser alocada no heap.
Quando a chamada delete
Recomendamos que você chamar DestroyWindow para destruir um objeto do Windows, o método de C++ ou o global DestroyWindow API.
Não chame o global DestroyWindow API para destruir uma janela filho MDI.Você deve usar o método virtual CWnd::DestroyWindow em vez disso.
Para a janela de C++ objetos que não execute a limpeza automática, usando o delete operador pode causar um vazamento de memória quando você tentar chamar DestroyWindow na CWnd::~CWnd destruidor se o VTBL não aponta para a classe derivada corretamente.Isso ocorre porque o sistema não consegue localizar que o apropriado método chamar destruir.Usando DestroyWindow em vez de delete evita esses problemas.Como isso pode ser um erro sutil, compilando no modo de depuração gera o seguinte aviso se estão em risco.
Warning: calling DestroyWindow in CWnd::~CWnd
OnDestroy or PostNcDestroy in derived class will not be called
No caso de objetos de C++ Windows executar limpeza automática, você deve chamar DestroyWindow.Se você usar o delete operador diretamente, o alocador de diagnóstico de memória do MFC avisará que você está liberando memória duas vezes.Duas ocorrências são sua primeira chamada explícita e indireta chamada para delete this na implementação de limpeza automática de PostNcDestroy.
Depois de chamar o DestroyWindow em um objeto de limpeza não automática, o objeto C++ continuará, mas m_hWnd será NULL.Depois de chamar o DestroyWindow um objeto de limpeza automática, o objeto C++ será desapareceu e liberada pelo operador delete C++ na implementação de limpeza automática de PostNcDestroy.