Définition de plusieurs des fonctions inline lors de la liaison de bibliothèques statiques
J'ai un programme en C++ que je compile avec mingw gcc pour Windows). À l'aide de la TDM version de mingw qui comprend gcc 4.4.1. L'exécutable deux liens vers des bibliothèque statique (.a) des fichiers: Sur d'eux est un tiers bibliothèque écrite en C; l'autre est une bibliothèque C++, écrit par moi, qui utilise la bibliothèque C donne mon propre API C++ sur le dessus.
Un (de mon point de vue, excessive, qui fait partie de la bibliothèque C de la fonctionnalité est implémentée dans les fonctions inline. Vous ne pouvez pas l'éviter, y compris les fonctions inline lorsque vous utilisez la bibliothèque C de l'API, mais quand j'essaie de les relier tous ensemble, j'obtiens des erreurs de lien disant qu'il y est un multiple de définition de toutes les fonctions inline - à la fois ceux que j'ai appelé dans mon wrapper C++ de la bibliothèque et ceux que je n'ai pas, en fait, tout objet défini en ligne dans les en-têtes a obtenu une fonction créée pour lui à la fois la bibliothèque C et le C++ de la bibliothèque.
Cela ne cause pas de définition de plusieurs erreurs lors de l'inclure des fichiers sont utilisés plusieurs fois dans différents .c ou .fichiers cpp dans le même projet; le problème est qu'elle génère une définition par la bibliothèque.
Comment/pourquoi le compilateur de générer des fonctions et des symboles pour ces fonctions inline dans les deux bibliothèques? Comment puis-je le forcer à arrêter de générer dans mon code? Est-il un outil que je peux courir à la bande de les dupliquer les fonctions de la .un fichier, ou une façon de faire de l'éditeur de liens ignorer les multiples définitions?
(Pour info, la troisième partie de la bibliothèque ne comprennent #ifdef __cplusplus et extern "C" gardes dans tous ses en-têtes, de toute façon si le problème était là, elle ne provoque pas d'une définition de plusieurs de symbole, il serait la cause du problème inverse parce que le symbole serait pas défini ou au moins différents.)
Notamment, le lien erreurs ne se produisent PAS si j'ai le lien de la troisième partie C de la bibliothèque de DLL; cependant, puis-je obtenir étrange runtime échecs qui semblent avoir à faire avec mon code avoir sa propre version de fonctions qu'il devrait appeler à partir de la DLL. (Comme si le compilateur est de créer des versions locales de fonctions que je n'ai pas demandé.)
Similaire versions de cette question ont déjà été posées, cependant, je n'ai pas trouvé la réponse à ma situation dans l'un de ces:
La réponse à cette question est que l'affiche a été de multiplier la définition variables, mon problème est multiple définition de fonctions inline: Répété Plusieurs Erreurs de Définition de y compris même en-tête dans plusieurs cpp
C'était un MSVC programme, mais je suis en utilisant mingw; aussi, l'affiche du problème dans cette question a été la définition d'une classe C++ constructeur à l'extérieur du corps de la classe dans un en-tête, tandis que mon problème est avec les fonctions C qui sont en ligne: Statique Lib Définition De Plusieurs Problème
Ce fou renommé tous sa C code C++ de fichiers et de son code C n'est pas C++-coffre-fort: Définition de plusieurs de beaucoup de std:: fonctions lors de la liaison
C'était juste envie de savoir pourquoi violation de l'une définition de la règle n'était pas une erreur: le comportement imprévisible des fonctions Inline avec des définitions différentes
extern
, il crée une définition externe - ce qui n'est pas une ligne de définition de plus. Ces définitions ne peuvent apparaître plusieurs fois dans le programme. En C++ explicite extern
sur une telle fonction n'a aucun effet. Vous êtes mieux de faire static inline
en C.Normalement la fonction inline définitions sont marqués comme "faible", les symboles et l'éditeur de liens est censé supprimer tous les doublons.
Merci Johannes: à l'aide de définitions de préprocesseur, la bibliothèque C de l'en-tête des fichiers de déclarer ces fonctions "inline" si dans le C de la bibliothèque .c fichiers, et "extern inline", quand ils sont dans mon projet. Mais je ne sais pas pourquoi ils ont fait ça de cette façon. La bibliothèque C possède un code qui utilise l'adresse d'une fonction comme une valeur de clé unique. En tant que programmeur C++ j'ai vue que comme une mauvaise pratique et vraiment, je prie pour qu'ils n'utilisent pas l'adresse d'une fonction en ligne de cette façon. Je sens qu'il y a presque assez d'informations entre ces commentaires à mettre dans une réponse, bien que je n'arrive pas à compiler le programme.
Si il utilise l'adresse de la fonction comme une clé quelque part et s'appuie sur la même adresse à travers TUs, vous ne pouvez pas utiliser
static inline
plus. Vous pouvez utiliser -fgnu89-inline
et l'utilisation extern inline
même en C en mode, cependant (voir gcc.gnu.org/onlinedocs/gcc/Inline.html . Si vous compilez sans -std=c99
, il peut même être à la mode, en effet, de toute façon, déjà, je pense).J'ai ajouté le "C" de la balise à cette question (car on ne peut pas avoir 6 tag) suppression de la "multi-définition de l'erreur", qui semble être couverte par des "liens d'erreur" trop.
OriginalL'auteur Dennis | 2010-02-07
Vous devez vous connecter pour publier un commentaire.
D'abord, vous devez comprendre le C99 inline modèle - peut-être il ya quelque chose de mal avec votre en-têtes. Il y a deux sortes de définitions pour les fonctions inline avec externe (non statique) couplage
Définition externe
Cette définition d'une fonction ne peut apparaître qu'une fois dans tout le programme, dans un espace de TU. Il fournit une fonction exportée qui peut être utilisé à partir d'autres TUs.
Inline définition
Ceux-ci apparaissent dans chaque TU où déclarée comme une définition distincte. Les définitions ne pas besoin d'être identique à un autre ou à l'extérieur de la définition. Si utilisé dans une bibliothèque, ils peuvent faire omettre de vérifier sur les arguments d'une fonction qui serait autrement être fait dans la définition externe.
Chaque définition de la fonction a ses propres variables statiques, parce que leurs locaux déclarations ont pas de lien (ils ne sont pas partagés comme en C++). Une définition de la non-statique de la fonction en ligne sera une ligne de définition si
inline
, etextern
.Autrement, la définition qui doit apparaître dans que TU (car les fonctions inline doit être défini dans le même TU où déclarée) est une définition externe. Dans un appel à une fonction inline c'est pas spécifié si l'externe ou de la ligne de définition est utilisée. Cependant, parce que la fonction définie dans tous les cas, est toujours le même (parce qu'il a une liaison externe), l'adresse de celui-ci compare l'égalité dans tous les cas, peu importe la façon dont de nombreux inline définitions apparaissent. Donc, si vous prenez l'adresse de la fonction, il est probable que le compilateur résout à la définition externe (en particulier si des optimisations sont désactivés).
Un exemple qui démontre une mauvaise utilisation de
inline
, car il inclut une définition externe d'une fonction deux fois en deux TUs, provoquant une définition de plusieurs erreurLe programme suivant est dangereux, parce que le compilateur est libre d'utiliser la définition externe, mais le programme ne fournit pas un
J'ai fait des cas de test à l'aide de GCC que démontrer le mécanisme plus loin:
principal.c
main1.c
main2.c
Maintenant, le programme des sorties de ce que nous attendions!
En regardant la table des symboles, nous allons voir que le symbole d'une ligne de définition n'est pas exporté (à partir de
main1.o
), tandis qu'une autre définition est exporté (à partir demain2.o
).Maintenant, si vos bibliothèques statiques ont chacun une définition externe de leurs fonctions inline (comme ils le devraient), ils seront naturellement en conflit les uns avec les autres. La solution est de rendre les fonctions inline statique ou tout simplement à les renommer. Ces fournira toujours des définitions externes (de sorte qu'ils sont à part entière des définitions), mais ils ne sont pas exportés parce qu'ils ont une liaison interne, donc pas contradictoires
Pour de plus amples informations, cette discussion indique le compilateur niveau d'optimisation peuvent affecter la question: lkml.indiana.edu/hypermail/linux/kernel/0408.0/1787.html
J'ai trouvé quelque chose de similaire lors de la construction avec MinGW gcc, et a découvert que la MinGW-têtes semblent être incompatibles avec l'option-std=gnu99 option. Cela a provoqué un beaucoup de multiplier les symboles définis quand j'ai essayé de faire un lien, que des définitions pour les fonctions ont été placés dans chaque fichier objet construit de cette façon.
...donc j'ai trouvé que l'utilisation par-fgnu89-inline est un solution de contournement pour notre cas, comme nous avons besoin de l'gnu99 portée sur pour-compteur de boucle variables. (pouah)
OriginalL'auteur Johannes Schaub - litb