96 votes

Comment détecter les fichiers #include inutiles dans un grand projet C++ ?

Je travaille sur un grand projet C++ dans Visual Studio 2008, et il y a beaucoup de fichiers avec des #include inutiles. Parfois, les #include ne sont que des artefacts et tout se compile bien s'ils sont supprimés. Dans d'autres cas, les classes peuvent être déclarées de manière anticipée et le #include peut être déplacé vers le fichier .cpp. Existe-t-il de bons outils pour détecter ces deux cas de figure ?

50voto

Eclipse Points 27662

Bien qu'il ne révèle pas les fichiers inclus inutiles, Visual Studio dispose d'un paramètre "/showIncludes" (clic droit sur un fichier .cpp, Propriétés->C/C++->Avancé) qui affiche un arbre de tous les fichiers inclus au moment de la compilation. Cela peut aider à identifier les fichiers qui n'ont pas besoin d'être inclus.

Vous pouvez également jeter un coup d'œil à l'idiome pimpl, qui vous permet de réduire le nombre de dépendances des fichiers d'en-tête afin de mieux voir les éléments que vous pouvez supprimer.

30voto

Joe Points 2507

Peluche de PC fonctionne très bien pour cela, et il trouve toutes sortes d'autres problèmes bizarres pour vous aussi. Il dispose d'options de ligne de commande qui peuvent être utilisées pour créer des outils externes dans Visual Studio, mais j'ai trouvé que l'option Visual Lint est plus facile à utiliser. Même la version gratuite de Visual Lint est utile. Mais donnez une chance à PC-Lint. Le configurer pour qu'il ne vous donne pas trop d'avertissements prend un peu de temps, mais vous serez étonné de ce qu'il trouve.

29voto

Josh Kelley Points 24438

Il y a un nouvel outil basé sur Clang, incluez ce que vous voulez qui vise à faire cela.

26voto

Richard Corden Points 12292

AVIS DE NON-RESPONSABILITÉ ! Je travaille sur un outil commercial d'analyse statique (pas PC Lint). AVERTISSEMENT !

Une approche simple sans analyse syntaxique pose plusieurs problèmes :

1) Sets de surcharge :

Il est possible qu'une fonction surchargée ait des déclarations qui proviennent de différents fichiers. Il se peut que la suppression d'un fichier d'en-tête entraîne le choix d'une surcharge différente plutôt qu'une erreur de compilation ! Le résultat sera un changement silencieux de la sémantique qui peut être très difficile à retracer par la suite.

2) Spécialisations des modèles :

Comme dans l'exemple de la surcharge, si vous avez des spécialisations partielles ou explicites pour un modèle, vous voulez qu'elles soient toutes visibles lorsque le modèle est utilisé. Il se peut que les spécialisations pour le modèle principal se trouvent dans différents fichiers d'en-tête. La suppression de l'en-tête contenant la spécialisation ne provoquera pas d'erreur de compilation, mais peut entraîner un comportement indéfini si cette spécialisation avait été sélectionnée. (Voir : http://stackoverflow.com/questions/59331/visibility-of-template-specialization-of-c-function )

Comme l'a souligné 'msalters', une analyse complète du code permet également d'analyser l'utilisation des classes. En vérifiant comment une classe est utilisée à travers un chemin spécifique de fichiers, il est possible que la définition de la classe (et donc toutes ses dépendances) puisse être supprimée complètement ou au moins déplacée à un niveau plus proche de la source principale dans l'arbre d'inclusion.

10voto

Graeme Perrow Points 22249

Je ne connais pas d'outils de ce type, et j'ai pensé en écrire un par le passé, mais il s'avère que c'est un problème difficile à résoudre.

Disons que votre fichier source comprend a.h et b.h ; a.h contient #define USE_FEATURE_X et b.h utilise #ifdef USE_FEATURE_X . Si #include "a.h" est commenté, votre fichier peut toujours compiler, mais peut ne pas faire ce que vous attendez. Détecter cela par programme est non trivial.

Quel que soit l'outil utilisé, il devra également connaître votre environnement de construction. Si a.h ressemble à :

#if defined( WINNT )
   #define USE_FEATURE_X
#endif

Puis USE_FEATURE_X n'est défini que si WINNT est définie, l'outil doit donc savoir quelles directives sont générées par le compilateur lui-même et lesquelles sont spécifiées dans la commande de compilation plutôt que dans un fichier d'en-tête.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X