web-dev-qa-db-fra.com

Détecter des #includes superflus en C/C++?

Je trouve souvent que la section d'en-tête d'un fichier devient de plus en plus grande mais qu'elle ne diminue jamais. Tout au long de la vie d'un fichier source, les classes peuvent avoir été déplacées et refactorisées et il est fort possible qu'il existe un nombre considérable de #includes qui n'ont plus besoin d'être présents. Les laisser là ne fait que prolonger le temps de compilation et ajoute des dépendances inutiles à la compilation. Essayer de trouver ce qui est encore nécessaire peut être assez fastidieux.

Existe-t-il un type d’outil permettant de détecter les directives #include superflues et de suggérer celles que je peux supprimer en toute sécurité?
Est-ce que les peluches font ça peut-être?

246
shoosh

Ce n'est pas automatique, mais doxygen produira des diagrammes de dépendance pour les fichiers #included. Vous devrez les examiner visuellement, mais ils peuvent être très utiles pour obtenir une image de ce qui utilise quoi.

39
anon

Le logiciel cppclean de Google (liens vers: download , documentation ) peut détecter plusieurs catégories de problèmes C++, et il peut désormais rechercher des #includes superflus.

Il existe également un outil basé sur Clang, include-what-you-use , qui peut le faire. include-what-you-use peut même suggérer des déclarations en aval (pour que vous n'ayez pas à #inclure autant) et éventuellement nettoyer votre #inclus pour vous. 

Les versions actuelles de Eclipse CDT intègrent également cette fonctionnalité: aller dans le menu Source et cliquer sur Organiser les inclusions va alphabétiser votre # inclus, ajouter les en-têtes qu'Eclipse pense utiliser sans les inclure en-têtes dont il ne pense pas avoir besoin. Cette fonctionnalité n'est toutefois pas fiable à 100%.

148
Josh Kelley

Consultez également include-what-you-use , qui résout un problème similaire. 

57
Tzafrir

Le problème avec la détection d'inclusions superflues est qu'il ne peut pas s'agir simplement d'un vérificateur de dépendance de type. Une inclusion superflue est un fichier qui n’a aucune valeur pour la compilation et ne modifie pas un autre élément dont dépendent d’autres fichiers. Un fichier d’en-tête peut modifier une compilation de plusieurs manières, par exemple en définissant une constante, en redéfinissant et/ou en supprimant une macro utilisée, en ajoutant un espace de nom qui modifie la recherche d’un nom en aval. Afin de détecter des éléments tels que l'espace de noms dont vous avez besoin bien plus qu'un préprocesseur, vous avez en fait presque besoin d'un compilateur complet. 

Lint est plus un vérificateur de style et n'aura certainement pas cette capacité complète. 

Je pense que vous trouverez que le seul moyen de détecter une inclusion superflue consiste à supprimer, compiler et exécuter des suites. 

24
JaredPar

Je pensais que PCLint ferait cela, mais cela fait quelques années que je ne l’ai pas examiné. Vous pourriez le vérifier.

J'ai regardé ce blog et l'auteur a parlé un peu de la configuration de PCLint pour trouver les inclus non utilisés. Ça vaut peut-être le coup d'oeil.

15
itsmatt

Le navigateur CScout refactoring peut détecter les directives d’inclusion superflues dans le code C (malheureusement pas C++). Vous pouvez trouver une description de son fonctionnement dans this article de journal.

7

Vous pouvez écrire un script rapide qui efface une seule directive #include, compile les projets et enregistre le nom dans le fichier #include et le fichier dont il a été supprimé dans le cas où aucune erreur de compilation ne s’est produite.

Laissez-le fonctionner pendant la nuit et le lendemain, vous aurez une liste 100% correcte des fichiers à inclure que vous pouvez supprimer.

Parfois, la force brute ne fonctionne que :-)


edit: et parfois ce n'est pas le cas :-). Voici quelques informations tirées des commentaires:

  1. Parfois, vous pouvez supprimer deux fichiers d'en-tête séparément, mais pas les deux ensemble. Une solution consiste à supprimer les fichiers d'en-tête lors de l'exécution et non à les ramener. Ceci trouvera une liste de fichiers que vous pouvez supprimer en toute sécurité, bien qu'il puisse y avoir une solution avec plus de fichiers à supprimer que cet algorithme ne trouvera pas. (C'est une recherche gourmande sur l'espace des fichiers d'inclusion à supprimer. Elle ne trouvera qu'un maximum local)
  2. Il peut y avoir des changements subtils dans le comportement si certaines macros sont redéfinies différemment en fonction de certains #ifdefs. Je pense que ce sont des cas très rares, et les tests unitaires qui font partie de la construction devraient détecter ces changements.
6
Gilad Naor

Je n'ai jamais trouvé un outil à part entière qui réponde à vos attentes. La chose la plus proche que j'ai utilisée est IncludeManager , qui représente graphiquement votre arbre d'inclusion d'en-tête afin que vous puissiez repérer visuellement des éléments tels que les en-têtes inclus dans un seul fichier et les inclusions d'en-tête circulaires.

5
Dan Olson

Désolé de (re) poster ici, souvent les gens ne développent pas les commentaires.

Vérifiez mon commentaire sur crashmstr, FlexeLint/PC-Lint le fera pour vous. Message d'information 766. La section 11.8.1 de mon manuel (version 8.0) en parle.

En outre, et ceci est important, continuez à itérer jusqu'à ce que le message disparaisse . En d'autres termes, après avoir supprimé les en-têtes non utilisés, ré-exécutez lint, davantage de fichiers d'en-tête risquent de devenir "inutiles" une fois que vous en aurez supprimé. (Cela peut paraître idiot, lisez-le lentement et analysez-le, c'est logique.)

5
Dan

Si vous utilisez Eclipse CDT, vous pouvez essayer http://includator.com , qui est gratuit pour les bêta-testeurs (au moment de la rédaction de cet article) et supprime automatiquement les #includes superflus ou ajoute ceux qui manquent. Pour les utilisateurs disposant de FlexeLint ou de PC-Lint et utilisant Elicpse CDT, http://linticator.com pourrait être une option (également gratuite pour le test bêta). Bien qu'il utilise l'analyse de Lint, il fournit des solutions rapides pour supprimer automatiquement les instructions superflues #include.

4
PeterSom

Pour terminer cette discussion, le préprocesseur c ++ est terminé. C'est une propriété sémantique, qu'une inclusion soit superflue. Il découle donc du théorème de Rice qu'il est indécidable de savoir si une inclusion est superflue ou non. Il NE PEUT PAS y avoir de programme qui détecte (toujours correctement) si un include est superflu.

2
Algoman

Il existe un outil gratuit Inclure les dépendances de fichiers Watcher qui peut être intégré à Visual Studio. Il montre les #includes superflus en rouge.

2
Vladimir

Cet article explique une technique de suppression de #include en utilisant l'analyse syntaxique de Doxygen. C'est juste un script Perl, donc c'est assez facile à utiliser.

2
Steve Gury

J'ai essayé d'utiliser Flexelint (la version unix de PC-Lint) et les résultats sont mitigés. C'est probablement parce que je travaille sur une base de code très volumineuse et noueuse. Je recommande d'examiner attentivement chaque fichier signalé comme non utilisé.

L'inquiétude principale est les faux positifs. Les inclus multiples du même en-tête sont signalés comme un en-tête inutile. C’est grave, car Flexelint ne vous dit pas sur quelle ligne l’en-tête est inclus ni où il était auparavant.

L'un des moyens par lesquels les outils automatisés peuvent se tromper:

En A.hpp:

class A { 
  // ...
};

En B.hpp:

#include "A.hpp

class B {
    public:
        A foo;
};

En C.cpp:

#include "C.hpp"  

#include "B.hpp"  // <-- Unneeded, but lint reports it as needed
#include "A.hpp"  // <-- Needed, but lint reports it as unneeded

Si vous suivez aveuglément les messages de Flexelint, vous allez gâcher vos dépendances #include. Il y a plus de cas pathologiques, mais vous allez devoir inspecter vous-même les en-têtes pour obtenir les meilleurs résultats.

Je recommande vivement cet article sur Physical Structure et C++ du blog Games from inside. Ils recommandent une approche globale pour nettoyer le désordre #include:

Des lignes directrices

Voici un ensemble de directives tirées du livre de Lakos qui minimisent le nombre de dépendances physiques entre les fichiers. Je les utilise depuis des années et j'ai toujours été très heureux des résultats.

  1. Chaque fichier cpp comprend d'abord son propre fichier d'en-tête. [couper]
  2. Un fichier d'en-tête doit inclure tous les fichiers d'en-tête nécessaires à son analyse. [couper]
  3. Un fichier d'en-tête doit avoir le nombre minimum de fichiers d'en-tête nécessaire pour l'analyser. [couper]
2
Ben Martin

Voici un moyen simple force brute d’identifier les en-têtes superflus . Ce n'est pas parfait mais élimine l'inclus "évident" inutile. S'en débarrasser contribue grandement à nettoyer le code.

Les scripts sont accessibles directement sur GitHub.

1
ap-osd

Peut-être un peu tard, mais j’ai un jour trouvé un script WebKit Perl qui répondait exactement à vos attentes. Je crois qu'il faudra l'adapter (je ne connais pas très bien Perl), mais cela devrait faire l'affaire:

http://trac.webkit.org/browser/branches/old/safari-3-2-branch/WebKitTools/Scripts/find-extra-includes

(c'est une ancienne branche car trunk n'a plus le fichier)

1
rubenvb

Il existe deux types de fichiers #include superflus:

  1. Un fichier d'en-tête dont le module (.c, .cpp) n'a pas du tout besoin 
  2. Le module a besoin d’un fichier d’en-tête, mais il est inclus plus d’une fois, directement ou indirectement.

D'après mon expérience, il y a deux façons de le détecter:

  • gcc -H ou cl.exe/showincludes (résoudre le problème 2)

    Dans le monde réel, vous pouvez exporter CFLAGS = -H avant make, Si tous les fichiers Makefile ne remplacent pas les options CFLAGS. Ou, comme je l’ai utilisé, vous pouvez créer un wrapper cc/g ++ pour ajouter des options -H .__ de force à chaque appel de $ (CC) et $ (CXX). et préfixez le répertoire du wrapper .__ à la variable $ PATH , puis votre marque utilisera tout utilise votre commande wrapper à la place. Bien sûr, votre wrapper devrait invoquer le compilateur Real gcc. Cette astuce Doit changer si votre Makefile utilise directement Gcc. au lieu de $ (CC) ou $ (CXX) ou par des règles implicites.

    Vous pouvez également compiler un seul fichier en modifiant la ligne de commande. Mais si vous voulez nettoyer les en-têtes pour tout le projet. Vous pouvez capturer toute la sortie en:

    rendre propre

    faire 2> & 1 | tee result.txt

  • PC-Lint/FlexeLint (résoudre le problème 1 et 2)

    assurez-vous d’ajouter les options + e766, cet avertissement concerne: fichiers d’en-tête inutilisés.

    pclint/silex -vf ...

    Cela entraînera des fichiers d'en-tête inclus dans la sortie de pclint. Les fichiers d'en-tête imbriqués seront mis en retrait de manière appropriée.

1
zhaorufei

PC Lint de Gimpel Software peut indiquer quand un fichier d'inclusion a été inclus plusieurs fois dans une unité de compilation, mais il ne peut pas trouver les fichiers d’inclusion qui ne sont pas nécessaires à la manière que vous recherchez.

Modifier: Ça peut. Voir La réponse de itsmatt

0
crashmstr

CLion , le C/C++ IDE de JetBrains, détecte les éléments redondants inclus. Celles-ci sont grisées dans l'éditeur, mais il existe également des fonctions pour optimiser les inclus dans le fichier actuel ou le projet entier .

J'ai trouvé que vous payez pour cette fonctionnalité cependant; CLion prend un certain temps pour analyser et analyser votre projet lors de son premier chargement.

0
congusbongus