2010-08-17 4 views
4

Dans mon application, je veux exécuter la logique au tout dernier moment. Le plus tard, le mieux.Quel est le tout dernier endroit où vous pouvez exécuter la logique dans un exécutable Windows?

La raison en est que je garde une trace de certains éléments de mon application (structures de données, ressources, ...), et à la fin de l'application, une routine regarde ces éléments et les rapports s'ils n'étaient pas correctement fermé, libéré, supprimé, ...

Jusqu'à présent, nous l'avons fait en utilisant plusieurs astuces.

La première astuce consistait à annuler la fonction _heap_term du temps d'exécution C (ainsi que certaines autres fonctions du C Run Time). L'avantage est que cela a fonctionné très bien, mais se limitait aux applications dans lesquelles le CRT a été lié statiquement dans

La deuxième astuce consistait à définir une variable globale comme ceci:.

#pragma init_seg(lib) 
GlobalApplicationManager s_globalApplicationManager; 

Le pragma fait que que cette variable globale est construite avant toutes les autres variables globales, et - plus important encore - qu'elle est détruite après toutes les autres variables globales. De cette façon, nous pouvons mettre la logique de vérification dans le destructeur de cette classe.

Le problème est qu'à partir de Windows 7, le destructeur n'est plus appelé dans certaines situations. En ce moment, il n'est pas clair ce qui influence cela, mais nous sommes sûrs qu'il n'est pas appelé si nous réussissons une connexion Oracle dans notre application.

Quelles sont les autres astuces pour exécuter du code aussi tard que possible dans une application?

+3

Si les globals posent problème, la meilleure solution est peut-être de refactoriser votre code et de ne pas utiliser de globals. – ereOn

+1

convenu. Si vous avez de la difficulté à gérer la durée de vie de vos ressources, à créer des hacks * supplémentaires *, rendre la vie encore plus difficile à gérer semble à peine la bonne façon de procéder. – jalf

+0

@ereOn, je suis d'accord, mais les globales ne sont pas le seul problème. Ce que je veux, c'est une vérification intégrée des structures de données internes à la fin de l'application (y compris, et probablement le plus important, si toute la mémoire a été libérée correctement). Avant Windows 7, si notre application avait encore de la mémoire allouée à la toute fin, le développeur/tester/internaluser en était averti automatiquement. Cela a presque garanti que chaque développeur a été informé immédiatement de toute fuite de mémoire. Aucun outil externe n'était nécessaire, car les contrôles étaient intégrés. – Patrick

Répondre

7

Utilisez /ENTRYPOINT. Dans votre point d'entrée personnalisé, appelez le point d'entrée CRT, puis votre logique finale.

+0

Bonne idée originale. +1 – Patrick

2

Je pense que vous devriez essayer de refactoriser votre code: Toute variable membre doit être détruite dans le destructeur de classe concerné. Pour les variables globales, vous pouvez définir une fonction de destruction void func() et appeler atexit(func) lors de l'initialisation. Pour les variables globales, vous pouvez définir une fonction de destruction void func() et

+0

En théorie vous avez raison: le destructeur de classe devrait nettoyer ses propres choses. Le problème est qu'une partie de l'application est toujours en langage C. Et nous voulons que les contrôles supplémentaires avertissent les développeurs s'ils ont oublié de nettoyer certaines choses. D'où la logique de contrôle à la fin de l'application. Nous avons également envisagé d'utiliser atexit, mais apparemment, si les variables globales ne sont pas nettoyées, la fonction atexit n'est pas non plus appelée. Néanmoins, merci pour la suggestion. – Patrick

1

Il existe un certain nombre de sections définies par le CRT auxquelles vous pouvez ajouter vos propres appels avec #pragma. En utilisant le bon nom, vous pouvez ajouter du code à différents points du processus d'initialisation et d'arrêt. Cependant, les noms ne sont pas faciles à trouver.

Vérifiez "crt0dat.c" dans la source CRT installée avec VS2010 pour certains des noms.

0

Pourquoi ne pas simplement passer un message personnalisé à votre fenêtre/application après l'appel de ShowWindow?

1

Vous pouvez placer votre logique dans une fonction DllMain(DLL_PROCESS_DETACH) dans une DLL auxiliaire. Cela se produit même après le retour du point d'entrée du fichier EXE (en supposant que même les retours - cela ne soit pas dû à TerminateThread) donc c'est plus fiable et plus tard que la suggestion précédente de Ben Voigt. Par contre, ne supposez pas que vous pouvez en faire trop, par contre. C'est à peu près le dernier endroit où vous pouvez exécuter la logique, mais vous ne pouvez pas compter sur d'autres DLL étant plus présents. C'est tout le point de DLL_PROCESS_DETACH. Vous pouvez seulement compter sur Kernel32.DLL étant à gauche.

Questions connexes