365 votes

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

Je constate souvent que la section des en-têtes d'un fichier devient de plus en plus grande, mais qu'elle ne se réduit jamais. Tout au long de la vie d'un fichier source, les classes peuvent avoir été déplacées et remaniées, et il est très possible qu'il y ait un certain nombre d'en-têtes dans le fichier. #includes qui n'ont pas besoin d'être là et plus. Les laisser là ne fait que prolonger le temps de compilation et ajoute des dépendances de compilation inutiles. Essayer de déterminer lesquelles sont encore nécessaires peut être assez fastidieux.

Existe-t-il un outil capable de détecter les directives #include superflues et de suggérer celles que je peux supprimer sans risque ?
Est-ce que les peluches font ça peut-être ?

2 votes

2 votes

La question liée ne semble aborder le problème que sous Windows, en utilisant Visual Studio en particulier.

8 votes

Je vote pour rouvrir cette question, car le doublon concerne l'utilisation de Visual Studio, spécifiquement.

7voto

Diomidis Spinellis Points 8417

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

6voto

Dan Points 6319

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

Vérifiez mon commentaire à crashmstr, FlexeLint / PC-Lint fera cela pour vous. Message d'information 766. La section 11.8.1 de mon manuel (version 8.0) traite de ce sujet.

Aussi, et c'est important, continuez à itérer jusqu'à ce que le message disparaisse. . En d'autres termes, après avoir supprimé les en-têtes inutilisés, relancez lint, d'autres fichiers d'en-tête pourraient être devenus "inutiles" une fois que vous avez supprimé certains en-têtes inutiles. (Cela peut sembler stupide, lisez-le lentement et analysez-le, cela a du sens).

5voto

Dan Olson Points 11210

Je n'ai jamais trouvé d'outil complet permettant de réaliser ce que vous demandez. La chose la plus proche que j'ai utilisée est IncludeManager qui représente graphiquement l'arbre d'inclusion des en-têtes 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êtes circulaires.

4voto

Gilad Naor Points 5377

Vous pouvez écrire un script rapide qui efface une seule directive #include, compile les projets et consigne le nom dans le #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 inclus que vous pouvez supprimer.

Parfois, la force brute fonctionne simplement :-)


éditer : et parfois non :-). 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 pendant l'exécution et à ne pas 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. (il s'agit d'une recherche avide sur l'espace des fichiers inclus à supprimer. Il 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 certaines #ifdefs. Je pense que ce sont des cas très rares, et les tests unitaires qui font partie de la construction devraient attraper ces changements.

4voto

Ben Martin Points 370

J'ai essayé d'utiliser Flexelint (la version unix de PC-Lint) et j'ai obtenu des résultats quelque peu mitigés. C'est probablement parce que je travaille sur une base de code très large et noueuse. Je recommande d'examiner attentivement chaque fichier qui est signalé comme inutilisé.

Le principal souci est celui des faux positifs. Les inclusions multiples du même en-tête sont signalées comme un en-tête non nécessaire. C'est mauvais puisque Flexelint ne vous dit pas sur quelle ligne l'en-tête est inclus ou où il a été inclus auparavant.

Les outils automatisés peuvent notamment se tromper :

Dans A.hpp :

class A { 
  // ...
};

Dans 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 existe des cas plus pathologiques, mais en gros, vous devrez inspecter les en-têtes vous-même pour obtenir les meilleurs résultats.

Je recommande vivement cet article sur Structure physique et C++ du blog Jeux de l'intérieur. Ils recommandent une approche globale pour nettoyer le désordre #include :

Directives

Voici un ensemble de directives distillé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 satisfait des résultats.

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

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