web-dev-qa-db-fra.com

GCC ne peut-il pas se plaindre de références non définies?

Dans quelle situation est-il possible pour GCC de pas envoyer un message d'erreur de lien "référence non définie" lors de la tentative d'appeler des fonctions composées?

Par exemple, une situation dans laquelle ce code C est compilé et lié par GCC:

void function()
{
    made_up_function_name();
    return;
}

...même si made_up_function_name n'est pas présent n'importe où dans le code (pas les en-têtes, les fichiers source, les déclarations, ni aucune bibliothèque tierce).

Ce type de code peut-il être accepté et compilé par GCC sous certaines conditions, sans toucher au code réel? Si oui, lequel?

Merci.

EDIT: aucune déclaration ou mention précédente à made_up_function_name sont présents ailleurs. Cela signifie qu'un grep -R de l'ensemble du système de fichiers niquement affichera cette seule ligne de code exacte.

49
STenyaK

Oui, il est possible d'éviter de signaler des références non définies - en utilisant --unresolved-symbols option de l'éditeur de liens.

g++ mm.cpp -Wl,--unresolved-symbols=ignore-in-object-files

De man ld

- unresolved-symboles = méthode

Déterminez comment gérer les symboles non résolus. Il existe quatre valeurs possibles pour la méthode:

       ignore-all
           Do not report any unresolved symbols.

       report-all
           Report all unresolved symbols.  This is the default.

       ignore-in-object-files
           Report unresolved symbols that are contained in shared
           libraries, but ignore them if they come from regular object
           files.

       ignore-in-shared-libs
           Report unresolved symbols that come from regular object
           files, but ignore them if they come from shared libraries.  This
           can be useful when creating a dynamic binary and it is known
           that all the shared libraries that it should be referencing
           are included on the linker's command line.

Le comportement des bibliothèques partagées peut également être contrôlé par l'option - [no-] allow-shlib-undefined.

Normalement, l'éditeur de liens génère un message d'erreur pour chaque symbole non résolu signalé, mais l'option --warn-unresolved-symbol peut le transformer en avertissement.

84
Dmitry Yudakov

Si vous déclarez le prototype de la fonction avant de l'utiliser, il doit être compilé. Quoi qu'il en soit, l'erreur pendant la liaison restera.

void made_up_function_name();
void function()
{
    made_up_function_name();
    return;
}
3
Heisenbug

TL; DR Il peut ne pas se plaindre, mais vous ne le faites pas le veulent. Votre code se bloquera si vous forcez l'éditeur de liens à ignorer le problème. Ce serait contre-productif.

Votre code repose sur l'ancien C (pré-C99) permettant aux fonctions d'être déclarées implicitement à leur point d'utilisation. Votre code est sémantiquement équivalent au code suivant:

void function()
{
    int made_up_function_name(...); // The implicit declaration

    made_up_function_name(); // Call the function
    return;
}

L'éditeur de liens se plaint à juste titre que le fichier objet qui contient la function() compilée fait référence à un symbole qui n'a été trouvé nulle part ailleurs. Vous devez le corriger en fournissant l'implémentation pour made_up_function_name()ou en supprimant l'appel absurde. C'est tout. Aucun jeu de liens n'est nécessaire.

2
Kuba Ober

Et puis il y a cette méchanceté avec le drapeau -D passé à GCC.

$cat undefined.c
void function()
{
    made_up_function_name();
    return;
}


int main(){
}

$gcc undefined.c -Dmade_up_function_name=atexit
$

Imaginez simplement que vous recherchez la définition de made_up_function_name - elle n'apparaît nulle part encore "fait des choses" dans le code. Je ne peux pas penser à une bonne raison de faire exactement cela dans le code.

L'indicateur -D est un outil puissant pour changer le code au moment de la compilation.

2
Tim Williscroft

Lorsque vous générez avec l'indicateur de l'éditeur de liens -r ou --relocatable il ne produira pas non plus de message d'erreur de lien "référence non définie".

Ceci est dû au fait -r liera différents objets dans un nouveau fichier objet à lier ultérieurement.

1
Sjors Telgen

L'algorithme "standard" selon lequel opèrent les éditeurs de liens POSIX laisse ouverte la possibilité que le code se compile et se lie sans erreur. Voir ici pour plus de détails: https://stackoverflow.com/a/11894098/18769

Afin d'exploiter cette possibilité, le fichier objet qui contient votre function (appelons-le f.o) doit être placé dans une bibliothèque. Cette bibliothèque doit être mentionnée dans la ligne de commande du compilateur (et/ou de l'éditeur de liens), mais à ce moment aucun autre fichier objet (mentionné précédemment dans la ligne de commande) ne devrait avoir fait d'appels à function ou à tout autre fonction présente dans f.o. Dans de telles circonstances, l'éditeur de liens ne verra aucune raison de récupérer f.o de la bibliothèque. Linker ignorera complètement f.o, ignore complètement function et, par conséquent, ignore complètement l'appel à made_up_function_name. Le code sera compilé même si made_up_function_name n'est défini nulle part.

0
AnT