4 votes

Faire en sorte que le linker de GCC soit averti des définitions de fonctions multiples

Considérez mon petit exemple de bibliothèque C :

#include <external_library.h>

void some_function(void)
{
    external_library_call();
    // Do other stuff...
}

Elle prévoit de rendre la fonction some_function() publiquement appelable. La bibliothèque ne fonctionne pas, cependant, parce que la bibliothèque externe qu'elle requiert utilise également une fonction appelée some_function(), qui a le même prototype. L'éditeur de liens de GCC ne se soucie pas du nombre de sources du symbole some_function. Il en choisit une apparemment au hasard et la bibliothèque externe peut ou non utiliser ma some_function() au lieu de la sienne. C'est insensé. Pas le fait que la bibliothèque ne fonctionne pas. Cette bibliothèque ne devrait définitivement pas fonctionner. C'est plutôt le fait qu'il y ait deux sources pour le symbole 'some_function', mais que l'éditeur de liens ne fasse rien à ce sujet. Et vous savez, cela ne me dérange pas trop parce que je suis habitué à ce que GCC et le C en général soient pathologiquement imprudents par défaut. Il doit y avoir un moyen, cependant, pour que l'éditeur de liens m'avertisse quand il y a deux sources pour le même symbole. J'ai déjà essayé -Wall -Wextra -Wshadow, mais cela ne produit aucun avertissement.

Notez que -fvisibility=hidden ne sera pas utile ici car les deux bibliothèques veulent exporter some_function(). Je sais que vous pouvez dire que j'ai honte de faire des appels de fonctions sans préfixe unique. Vous avez raison. C'est une erreur. Mais je m'en moque. Cette erreur est rattrapable par l'éditeur de liens et doit donc être rattrapée. Il n'y a aucune raison pour que l'éditeur de liens n'attrape pas cette erreur. De plus, la bibliothèque que vous utilisez peut exporter des symboles étranges et inattendus, et vous n'avez pas nécessairement le contrôle sur ce que la bibliothèque de quelqu'un d'autre exporte. De plus, les préfixes ne peuvent pas être uniques avant que le programmeur ne s'arrête et ne prenne feu.

1voto

Nikos C. Points 18676

Ajouter :

\-fvisibility=hidden

à vos drapeaux de construction. Notez cependant quelques avertissements ; certains en-têtes peuvent ne pas s'attendre à cela. Dans ces cas, vous devez utiliser un pragma avant de les inclure :

#pragma GCC visibility push(hidden)
#include <problematic_header>
#pragma GCC visibility pop

Cela présente d'autres avantages que celui d'éviter les collisions de symboles. Voir :

http://gcc.gnu.org/wiki/Visibility

Au cas où vous seriez intéressé.

0voto

Jonathan Leffler Points 299946

Des options telles que -Wall -Wextra -Wshadow sont des drapeaux de compilateur qui affectent l'analyse du code source ; apparemment, vous cherchez une option de l'éditeur de liens.

Toutefois, étant donné que shutdown() se trouve dans l'espace de noms réservé à l'application (et vous ne montrez même pas que vous avez inclus l'en-tête qui déclare le système shutdown() ), il n'y a pas grand chose que le compilateur ou l'éditeur de liens puisse faire. En tant que programmeur de l'application, vous avez le droit de créer une fonction appelée shutdown() et l'appeler. Vous pouvez regarder quelque chose comme la suite de conformité LSB (Linux Standards Base) pour vérifier que vous ne définissez pas des fonctions qui sont définies par l'implémentation.

L'un des bogues les plus difficiles que j'ai eu à localiser impliquait une fonction _bind() dans notre code qui se trouvait être le même nom qu'une fonction du système _bind() qui avait une interface différente. Quand notre fonction a été appelée par des parties de la bibliothèque du système, l'enfer s'est déchaîné. C'était en partie notre faute pour avoir utilisé un nom réservé au système (ne pas commencer les noms de variables ou de fonctions par _ ), il était regrettable qu'une seule plateforme ait le nom de collision. Un préfixe systématique à notre _bind() a résolu le problème.

Vous pouvez consulter les listes de noms réservés dans les normes C et POSIX. Cependant, vous constaterez que les noms _t est réservé, mais les noms de type avec le suffixe sont largement (ab)utilisés pour les types définis par l'utilisateur également. Vous devez également savoir si une définition donnée du type provient d'un en-tête système (probablement OK), d'un en-tête défini par l'utilisateur (probablement pas OK) ou d'un en-tête défini par l'utilisateur fournissant une fonctionnalité système manquante (limite). Cela devient très délicat.

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