web-dev-qa-db-fra.com

Existe-t-il un moyen d'être averti des fonctions inutilisées?

Je voudrais trouver des fonctions inutilisées dans une base de code - y compris entre les unités de compilation. J'utilise gcc comme compilateur.

Voici un exemple:

foo.c (Supposez que foo.h Approprié):

void foo() {
   ....
}

void bar() {
   ....
}

main.c:

#include <stdio.h>
#include "foo.h"  

int main(void)  {
    bar();
    return 0;
}

Dans cet exemple, je voudrais être averti que foo() n'est pas utilisé.

Il y a l'option -Wunused-function Gcc:

-Wunused-function

Avertir chaque fois qu'une fonction statique est déclarée mais non définie ou qu'une fonction statique non intégrée n'est pas utilisée. Cet avertissement est activé par -Wall.

mais ce n'est que pour les fonctions statiques - cela ne produira pas d'avertissement sur l'exemple ci-dessus.

J'accepterai également des suggestions d'outils/scripts/autres compilateurs qui peuvent le faire pour moi - bien que je préfère m'en tenir à gcc si possible.

45
Timothy Jones

Caolan Mc Namara , un développeur LibreOffice, a créé un petit outil pour détecter ce type de chose dans le code source de LibreOffice. Ils avaient environ des milliers de fonctions et méthodes inutilisées dans LibreOffice. Son outil est un élément clé pour les supprimer.

Cela s'appelle callcatcher . Ça peut

collecter les fonctions/méthodes définies et soustraire appelées/référencées

Il fonctionne directement sur la sortie de l'assembleur et donc, il ne fonctionne que pour l'architecture x86 et x86_64. Il peut produire une sortie comme this . Vous pouvez l'intégrer à votre appel traditionnel de compilation et de liaison à gcc.

Caolan accepte qu'il devienne un plugin gcc.

43
Coren

Je sais que vous avez demandé des avertissements et préférez ne pas utiliser l'option gcc mais c'est vraiment facile.

Vous pouvez utiliser l'optimisation de l'éditeur de liens (--gc-sections) afin de supprimer le code mort de votre application.

Depuis la page de manuel de gcc:

- gc-sections --no-gc-sections Active le ramasse-miettes des sections d'entrée inutilisées. Il est ignoré sur les cibles qui ne prennent pas en charge cette option. Le comportement par défaut (de ne pas effectuer cette récupération de place) peut être restauré en spécifiant --no-gc-sections sur la ligne de commande.

- gc-sections décide quelles sections d'entrée sont utilisées en examinant les symboles et les délocalisations. La section contenant le symbole d'entrée et toutes les sections contenant des symboles non définis sur la ligne de commande seront conservées, de même que les sections contenant des symboles référencés par des objets dynamiques. Notez que lors de la création de bibliothèques partagées, l'éditeur de liens doit supposer que tout symbole visible est référencé. Une fois que cet ensemble initial de sections a été déterminé, l'éditeur de liens marque récursivement comme utilisé toute section référencée par leur relocalisation. Voir --entry et --undefined.

Cette option peut être définie lorsque vous effectuez un lien partiel (activé avec l'option -r). Dans ce cas, la racine des symboles conservés doit être explicitement spécifiée soit par une option --entry ou --undefined, soit par une commande "ENTRY" dans le script de l'éditeur de liens.

4
eyalm

Tout d'abord, si vous voulez que ces avertissements soient à l'échelle du programme, vous avez certainement besoin du -flto flag, car il doit être résolu au moment de la liaison, pas au moment de la compilation de chaque unité individuelle. Mais je ne pense pas que GCC fournisse de tels avertissements, même de cette façon.

Ensuite, dans le cas général, je comprendrais qu'il ne serait pas judicieux de le fournir (parce que par exemple le libc lié a probablement beaucoup de fonctions dont votre application n'a pas besoin). De plus, une application pourrait utiliser dlsym astuces pour atteindre une fonction apparemment non appelée ...

Cependant, c'est un bon exemple d'un cas d'utilisation potentiel pour un plugin GCC ou une extension MELT , qui enregistrerait chaque occurrence d'appel quelque part, avec une recherche d'utilitaire ultérieure toutes les fonctions non appelées. (Mais coder un plugin ou une extension MELT pour GCC vous prendra au moins plusieurs jours, car vous devrez comprendre les internes de GCC).

Vous pouvez également utiliser des techniques de profilage pour obtenir les fonctions dynamiquement inutilisées (non appelées).

N'hésitez pas à m'en demander plus par mail.

3

Eclipse CDT possède une analyse de code, que vous pouvez définir pour marquer les fonctions statiques inutilisées et les déclarations de fonctions inutilisées (entre autres choses utiles). Comme déjà dit, seul l'éditeur de liens pouvait dire que certaines fonctions (non statiques) n'étaient pas utilisées dans certains binaires ...

1
dbrank0

gprof est la solution la plus simple je suppose. J'ai compilé l'exemple de programme que vous avez mis en place avec -pg option pour obtenir le gmon.out lorsque nous exécutons a.out (que gprof pourra utiliser plus tard), puis j'ai finalement exécuté gprof -z a.out gmon.out | tee output.txt. J'ai pu trouver votre fonction foo dans la liste inutilisée! c'est-à-dire appelé 0 fois. -z est l'option que vous devez utiliser avec gprof pour suivre les routines inutilisées.

Merci à this thread pour le pointeur approprié!

PS: gprof a jeté un tas d'autres fonctions de bibliothèque inutilisées avec votre fonction inutilisée foo. Je ne sais vraiment pas comment filtrer ça :)

1
Pavan Manjunath