2010-06-23 3 views
3

Récemment, j'ai rencontré un problème dans mon projet. Je compile normalement dans gcc-4, mais après avoir essayé de compiler dans gcc-3, j'ai remarqué un traitement différent des fonctions inline. Pour illustrer cela, je l'ai créé un exemple simple:gcc - 2 versions, traitement différent des fonctions en ligne

main.c:

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

int main() 
{ 
    printf("f() %i\n", f()); 
    return 0; 
} 

file.c:

#include "header.h" 
int some_function() 
{ 
    return f(); 
} 

header.h

inline int f() 
{ 
    return 2; 
} 

Quand je compile le code en gcc-3.4.6 avec:

gcc main.c file.c -std=c99 -O2 

Je reçois une erreur de l'éditeur de liens (définition multiple de f), la même chose si je supprime l'indicateur -O2. Je sais que le compilateur n'a pas besoin de mettre en ligne quoi que ce soit s'il ne veut pas, donc je suppose qu'il a placé f dans le fichier objet au lieu de l'inscrire dans main.c et file.c, donc erreur de définition multiple. Évidemment, je pourrais corriger cela en rendant statique f, puis, dans le pire des cas, en ayant quelques f dans le binaire.

Mais j'ai essayé de compiler ce code dans gcc-4.3.5 avec:

gcc main.c file.c -std=c99 -O2 

Et tout a bien fonctionné, donc je suppose la nouvelle gcc inline f dans les deux cas et il n'y avait pas de fonction f dans le binaire du tout (vérifié dans gdb et j'avais raison).

Toutefois, lorsque j'ai supprimé le drapeau -O2, j'ai obtenu deux références non définies à int f(). Et là, je ne comprends vraiment pas ce qui se passe. Il semble que gcc supposé f soit inline, donc il ne l'a pas ajouté au fichier objet, mais plus tard (parce qu'il n'y avait pas -O2) il a décidé de générer des appels à ces fonctions au lieu d'inlining et c'est de là que vient l'erreur de linker .

Maintenant vient la question: comment dois-je définir et déclarer des fonctions simples et petites, que je veux en ligne, de sorte qu'ils puissent être utilisés tout au long du projet sans la crainte de problèmes dans divers compilateurs? Et est-ce que tout ce qui est statique est la bonne chose à faire? Ou peut-être gcc-4 est cassé et je ne devrais jamais avoir plusieurs définitions de fonctions inline dans quelques unités de traduction à moins qu'elles ne soient statiques?

Répondre

5

Oui, le comportement a été modifié à partir de gcc-4.3. Le document gcc inline (http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Inline.html) détaille ceci.

Petite histoire: plain inline sert uniquement à dire à gcc (dans l'ancienne version de toute façon) appels en ligne à partir de la même portée de fichier. Cependant, il ne dit pas à gcc que tous les appelants seraient de la portée du fichier, donc gcc conserve également une version lisible de f() autour de: ce qui explique l'erreur de vos symboles en double ci-dessus. Gcc 4.3 a changé ce comportement pour être compatible avec c99.

Et, pour répondre à votre question:

Maintenant vient la question: comment dois-je définir et déclarer des fonctions simples et petites, que je veux en ligne, de sorte qu'ils peuvent être utilisés tout au long du projet sans peur des problèmes dans divers compilateurs? Et est-ce que tout ce qui est statique est la bonne chose à faire? Ou peut-être gcc-4 est cassé et je ne devrais jamais avoir plusieurs définitions de fonctions inline dans quelques unités de traduction à moins qu'elles ne soient statiques?

Si vous souhaitez une portabilité entre versions gcc, utilisez static inline.

+0

Merci, cela explique beaucoup –