2010-07-06 17 views
1

Jusqu'à présent, je n'avais jamais vraiment besoin de l'application Winapp ExitInstance() d'une grande application MFC (Single Document Interface si c'est important) sur laquelle je travaille. Mais maintenant je le fais, principalement pour nettoyer les alocations de mémoire, décharger quelques DLL, etc. Eh bien, j'ai vite appris par les fuites de mémoire évidentes et telles que ExitInstance n'a pas été appelé. Ai-je manqué quelque chose d'évident? Dois-je ajouter manuellement quelque chose à la carte des messages pour m'assurer que mon override ExitInstance est appelé?ExitInstance non appelée dans l'application MFC

Je suppose que je peux faire mon nettoyage ailleurs, mais c'est le meilleur endroit si je peux le faire fonctionner. Intéressant, j'ai trouvé quelques exemples de ceci en tapant des chaînes comme "ExitInstance jamais appelé" et tel dans Google, et en aucun cas de vraies réponses offertes. L'application se ferme normalement lorsque quelqu'un clique sur la case de fermeture ou sur la touche "Quitter" du menu Fichier, et la fonction OnClose() de la fenêtre mainframe est toujours appelée. J'ai même essayé de forcer des choses en mettant AfxGetMainWnd() -> DestroyWindow(); dans cet événement OnClose() mainframe, mais je ne parviens toujours pas à exécuter ExitInstance(). Peut-être que c'est juste une grosse fonction fictive? Ou peut-être Je suis juste un gros mannequin? :-)

+0

Si votre application est dérivée de CWinApp, ExitInstance doit toujours être appelée. Si ce n'est pas le cas, cela n'est peut-être pas déclaré correctement ou votre application est terminée prématurément pour une raison quelconque. – humbagumba

+0

Je sais qu'il devrait, mais il ne le fait pas, même quand theres pas s'exécute, pas de hits, pas d'erreurs, et l'application se ferme avec le code 0. Wierd. Dois-je ajouter quelque chose à la carte des messages? Est-ce important si mon override ExitInstance() est également virtuel (ne devrait pas importer). Dois-je ajouter quelque chose à la carte de message pour m'assurer qu'elle est appelée? – Randy

+0

"Est-ce important si mon override ExitInstance() est aussi virtuel (ne devrait pas importer)." Cela n'a pas d'importance, car une fonction virtuelle surchargée est toujours virtuelle, que vous la marquiez comme telle ou non. –

Répondre

1

J'ai eu un problème similaire à vous ... le mien a été causé par le mélange Unicode et MBCS code construit .... peut-être que c'était votre cause sous-jacente?

J'ai dû convertir une application MBCS en Unicode, mais il était impossible de convertir l'ensemble du projet, donc j'ai dû mélanger Unicode compilé (l'application) et le code compilé MBCS (les DLL).

Certaines des DLL MBCS étaient des DLL d'extension MFC, d'autres étaient des DLL normales. L'une des DLL d'extension MFC contenait des ressources (liste d'images bitmap et boîtes de dialogue communes).

Je n'ai pas converti la DLL en UNICODE car il y avait beaucoup de DLL dépendantes qui auraient également dû être converties, et en plus je n'avais pas besoin des contrôles dans les boîtes de dialogue communes pour supporter le texte Unicode. Donc j'ai gardé la DLL comme MBCS, et j'ai utilisé AfxSetResourceHandle avant d'utiliser n'importe quelle classe dans la DLL MBCS qui utilisait les ressources ..... pour que les ressources soient extraites directement de la DLL au lieu du MFC chaîne de ressources, car MFC n'a pas pu trouver les ressources non-Unicode dans le cas contraire.

Je suppose que MFC n'aime pas quand vous avez un mélange de code compilé Unicode et non-unicode contenant des ressources ..... les recherches dans la chaîne de ressources échouent (je suppose que cela a quelque chose à voir avec la conversion de ressources ID à une chaîne d'ID, par exemple via MAKEINTRESOURCE).

J'ai créé l'application principale UNICODE, et vérifié que les en-têtes C++ des classes des DLL MBCS utilisaient CStringA dans les prototypes de fonction, ou des chaînes larges acceptées et effectuaient la conversion en interne. Ce que j'ai trouvé était que mon application ne se terminerait pas correctement ... il resterait dans l'appel MFC CWinThread :: PumpMessage/AfxInternalPumpMessage(), et ExitInstance ne serait jamais appelé.

Pour le résoudre, dans mon CMainFrame :: OnDestroy() je mets comme suit les 2 dernières déclarations:

void CMainFrame::OnDestroy() 
{ 
    .... 

    CFrameWnd::OnDestroy(); 

    AfxPostQuitMessage(0); 
} 
1

J'ai eu le même problème. Il s'avère qu'il a été provoqué par certains messages étant prétraduits par l'objet CWinApp après la destruction de l'ordinateur central. Il serait frappé une vérification de validité au cours de ce traitement et juste renflouer au lieu de sortir à travers l'instance de sortie normale.Surcharge des applications Le message PreTranslate et renvoyé immédiatement en l'absence d'image principale a résolu le problème.

BOOL CYourAppClass::PreTranslateMessage(MSG* pMsg) 
{ 
    // If the main window has gone away there is no need to do pre-translation. 
    // If the pre-translation were allowed to proceed the 
    // CWinAppEx::PreTranslateMessage may bail out without calling 
    /// the app's ExitInstance nor destructing the app object. 
    if (!m_pMainWnd) 
     return FALSE; 

return CWinAppEx::PreTranslateMessage(pMsg); 
} 
0

Vous dites que « le OnClose() de la fenêtre de l'ordinateur central ne se doute toujours appelé ». J'ai eu un problème avec l'une de mes applications MFC; J'avais mis du code de nettoyage de thread dans le gestionnaire d'événement OnClose() de ma fenêtre, et il n'était pas appelé. Après un peu de douleur, j'ai mis le code de nettoyage de thread dans un gestionnaire d'événements OnDestroy(), et maintenant il est toujours appelé. Vous pouvez donc vérifier si votre gestionnaire d'événements OnClose() est toujours appelé.

0

J'avais exactement le même problème. Dans mon cas, le problème a été résolu en remplaçant PostNcDestroy dans CMainFrame. Il semble que le traitement de ce dernier message dans la fenêtre principale de trame, il fait tout le travail:

virtual void PostNcDestroy(); 

void CMainFrame::PostNcDestroy() 
{ 
} 
0

Une autre possibilité est qu'il ya un échec d'assertion qui se passe au milieu du processus d'arrêt. Par exemple en détruisant une fenêtre. J'ai trouvé que lorsque cela se produit, ExitInstance est également ignoré. Donc, juste avant de fermer votre application, effacez la fenêtre du journal de sortie/débogage et voyez si un tel message est imprimé. Si c'est le cas, résolvez le problème et voyez si ExitInstance est appelé à nouveau.