Question

Je sais que PC-Lint peut vous renseigner sur les en-têtes qui sont inclus mais non utilisés. Y at-il d'autres outils qui peuvent faire cela, de préférence sur linux?

Nous avons une grande base de code que dans les 15 dernières années a vu beaucoup de déplacer les fonctionnalités autour, mais rarement les directives #include restants supprimeront lorsque la fonctionnalité passe d'un fichier de mise en œuvre à l'autre, nous laissant avec un assez bon désordre par ce point. Je ne peux évidemment faire la chose minutieuse de supprimer toutes les directives #include et de laisser le compilateur me dire quels sont ceux à réintégrer du, mais je préfère résoudre le problème dans le sens inverse - trouver ceux non utilisés - plutôt que la reconstruction d'une liste de ceux utilisés.

Était-ce utile?

La solution

AVERTISSEMENT:. Mon travail de jour travaille pour une entreprise qui développe des outils d'analyse statique

Je serais surpris si la plupart (sinon tous) des outils d'analyse statique n'ont pas eu une certaine forme de contrôle de l'utilisation d'en-tête. Vous pouvez utiliser cette page wikipedia pour obtenir une liste des outils disponibles et les entreprises par courriel pour leur demander .

Certains points que vous pourriez considérer lorsque vous évaluez un outil:

Pour la fonction surcharge, vous voulez que tous les en-têtes contenant soient visibles surcharges, non seulement l'en-tête qui contient la fonction qui a été sélectionnée par la résolution de surcharge:

// f1.h
void foo (char);

// f2.h
void foo (int);


// bar.cc
#include "f1.h"
#include "f2.h"

int main ()
{
  foo (0);  // Calls 'foo(int)' but all functions were in overload set
}

Si vous prenez l'approche de la force brute, d'abord supprimer tous les en-têtes, puis les ajouter à nouveau jusqu'à ce qu'il compile, si « f1.h » est ajouté d'abord, puis le code compilera mais ont changé la sémantique du programme.

Une règle similaire applique lorsque vous avez partiel et spécialisations. Peu importe si la spécialisation est sélectionné ou non, vous devez vous assurer que toutes les spécialisations sont visibles:

// f1.h
template <typename T>
void foo (T);

// f2.h
template <>
void foo (int);

// bar.cc
#include "f1.h"
#include "f2.h"


int main ()
{
  foo (0);  // Calls specialization 'foo<int>(int)'
}

En ce qui concerne l'exemple de surcharge, l'approche de la force brutale peut entraîner un programme qui compile encore, mais a un comportement différent.

Un autre type d'analyse connexes que vous pouvez regarder dehors pour vérifier si les types peuvent être déclarés avant. Considérez ce qui suit:

// A.h
class A { };

// foo.h
#include "A.h"
void foo (A const &);

// bar.cc
#include "foo.h"

void bar (A const & a)
{
  foo (a);
}

Dans l'exemple ci-dessus, la définition de « A » n'est pas nécessaire, et que le fichier d'en-tête de « foo.h » peut être changé pour qu'il ait une déclaration avant que pour « A »:

// foo.h
class A;
void foo (A const &);

Ce type de contrôle permet également de réduire les dépendances d'en-tête.

Autres conseils

Voici un script qu'il fait:

#!/bin/bash
# prune include files one at a time, recompile, and put them back if it doesn't compile
# arguments are list of files to check
removeinclude() {
    file=$1
    header=$2
    perl -i -p -e 's+([ \t]*#include[ \t][ \t]*[\"\<]'$2'[\"\>])+//REMOVEINCLUDE $1+' $1
}
replaceinclude() {
   file=$1
   perl -i -p -e 's+//REMOVEINCLUDE ++' $1
}

for file in $*
do
    includes=`grep "^[ \t]*#include" $file | awk '{print $2;}' | sed 's/[\"\<\>]//g'`
    echo $includes
    for i in $includes
    do
        touch $file # just to be sure it recompiles
        removeinclude $file $i
        if make -j10 >/dev/null  2>&1;
        then
            grep -v REMOVEINCLUDE $file > tmp && mv tmp $file
            echo removed $i from $file
        else
            replaceinclude $file
            echo $i was needed in $file
        fi
    done
done

Jetez un oeil à dehydra .

Depuis le site Web:

  

dehydra est un outil d'analyse léger, pilotable, à usage général statique capable d'analyses spécifiques à l'application du code C ++. Dans le sens le plus simple, dehydra peut être considéré comme un outil de grep sémantique.

Il devrait être possible de trouver un script qui vérifie les fichiers #include inutilisés.

cppclean semble faire un travail décent de trouver les fichiers d'en-tête inutilisés. Je viens de commencer à l'utiliser. Il produit un peu de faux positifs. Il sera souvent trouver inutile inclut dans les fichiers d'en-tête, mais ce ne sera pas vous dire que vous avez besoin d'une déclaration avant de la classe associée, et l'on compte les besoins à déplacer le fichier source associé.

Si vous utilisez Eclipse CDT vous pouvez essayer Includator qui est gratuit pour les bêta-testeurs (au moment de cette écriture) et supprime automatiquement #includes superflus ou ajoute les disparus.

Disclaimer: Je travaille pour l'entreprise qui se développe Includator et ont utilisé pendant les derniers mois. Il fonctionne très bien pour moi, afin de lui donner un essai: -)

Pour autant que je sache, il n'y a pas un (ce n'est pas PC-Lint), ce qui est dommage, et surprenant. Je l'ai vu la suggestion de faire ce bit de pseudo-code (qui est essentiellement votre automatiser « processus laborieux »:

  

pour chaque fichier cpp
      pour chaque tête comprennent
          commentez les comprennent
          compiler le fichier cpp
          si (compile_errors)
              un-commentaire sur l'en-tête
          autre
              retirer la tête de cpp inclure

Mettez ça dans une nuit Cron, et il devrait faire le travail, en gardant la projcet en question sans en-têtes inutilisés (vous pouvez toujours l'exécuter manuellement, évidemment, mais ça va prendre beaucoup de temps pour exécuter). Le seul problème est quand ne comprenant pas un en-tête ne génère pas une erreur, mais produit encore du code.

Je l'ai fait manuellement et sa valeur dans le court (Oh, est-ce le long terme - Il prend beaucoup de temps?) Terme en raison du temps de compilation réduite:

  1. En-têtes moins pour analyser pour chaque fichier cpp.
  2. Moins de dépendances - tout le monde n'a pas besoin recompiler après changer pour un en-tête.

Il est aussi un processus récursif - chaque fichier d'en-tête qui reste dans l'examen des besoins pour voir si des fichiers d'en-tête il comprend peut être retiré. De plus, parfois, vous pouvez remplacer les déclarations de l'avant pour en-tête comprend.

Ensuite, le processus a besoin de répéter tous les quelques mois / an pour maintenir au-dessus des en-têtes restants.

En fait, je suis un peu agacé par compilateurs C ++, ils devraient être en mesure de vous dire ce n'est pas nécessaire -. Le compilateur Microsoft peut vous dire quand un changement dans un fichier d'en-tête peut être ignoré en toute sécurité lors de la compilation

Si quelqu'un est intéressé, je viens sur sourceforge frappé légèrement un petit outil Java COMAND en ligne pour faire exactement cela. Comme il est écrit en Java, il est évidemment runable sur linux.

Le lien pour le projet est https://sourceforge.net/projects/chksem /files/chksem-1.0/

La plupart des approches pour la suppression non utilisée comprend mieux travailler si vous assurez-vous que chacun de vos fichiers d'en-tête compile lui-même. Je l'ai fait assez rapidement comme suit (excuses pour les fautes de frappe - je tape ceci à la maison:

find . -name '*.h' -exec makeIncluder.sh {} \;

makeIncluder.sh contient:

#!/bin/sh
echo "#include \"$1\"" > $1.cpp

Pour chaque ./subdir/classname.h de fichier, cette approche crée un fichier appelé ./subdir/classname.h.cpp contenant la ligne

#include "./subdir/classname.h"

Si votre makefile dans le. répertoire compile tous les fichiers cpp et contient -I., puis juste recompiler testera que chaque fichier inclus peut compiler lui-même. Compiler dans votre IDE favori avec goto erreur et corriger les erreurs.

Lorsque vous avez terminé, find . -name '*.h.cpp' -exec rm {} \;

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top