Kann sich GCC nicht über undefinierte Referenzen beschweren?

Lesezeit: 6 Minuten

Benutzeravatar von STenyaK
STenyaK

In welcher Situation ist es GCC möglich nicht eine “undefinierte Referenz”-Link-Fehlermeldung ausgeben, wenn Sie versuchen, erfundene Funktionen aufzurufen?

Zum Beispiel eine Situation, in der dieser C-Code von GCC kompiliert und gelinkt wird:

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

…wenngleich made_up_function_name ist nicht hier irgendwo im Code (keine Header, Quelldateien, Deklarationen oder Bibliotheken von Drittanbietern).

Kann diese Art von Code unter bestimmten Bedingungen von GCC akzeptiert und kompiliert werden, ohne den eigentlichen Code zu berühren? Wenn ja, welche?

Vielen Dank.

EDIT: keine vorherigen Erklärungen oder Erwähnungen zu made_up_function_name sind woanders vorhanden. Das bedeutet, dass a grep -R des gesamten Dateisystems wird nur Zeigen Sie genau diese einzelne Codezeile.

  • Es kann (solange Sie C kompilieren, nicht C++). Was versuchst du aber zu erreichen?

    – Jerry Sarg

    5. April 2011 um 17:11 Uhr

  • Ich versuche nicht, irgendetwas zu erreichen, es passiert bereits und ich würde gerne wissen, warum es möglich ist. Der made_up_function_name ist tatsächlich in der endgültigen, verknüpften Binärdatei vorhanden, wenn ich “-g” verwende und die Datei mit einem Texteditor bearbeite.

    – STenjaK

    5. April 2011 um 17:17 Uhr


  • Warum, siehe: stackoverflow.com/questions/4914589/c-prototype-functions/…, stackoverflow.com/questions/4800102/… und wahrscheinlich einige mehr.

    – Jerry Sarg

    5. April 2011 um 17:20 Uhr

  • Für alle vorgeschlagenen Antworten muss die Funktion zumindest definiert werden, auch wenn der Prototyp optional ist. “made_up_function_name” ist nirgendwo definiert oder prototypisiert.

    – STenjaK

    5. April 2011 um 17:31 Uhr

  • das verhindert es verlinken erfolgreich, aber nicht vom Kompilieren.

    – Jerry Sarg

    5. April 2011 um 17:34 Uhr

Benutzeravatar von Dmitry Yudakov
Dmitri Judakow

Ja, es ist möglich, das Melden undefinierter Referenzen zu vermeiden – using --unresolved-symbols Linker-Option.

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

Aus man ld

–unresolved-symbols=Methode

Bestimmen Sie, wie mit nicht aufgelösten Symbolen umgegangen werden soll. Es gibt vier mögliche Werte für Methode:

       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.

Das Verhalten für gemeinsam genutzte Bibliotheken allein kann auch durch die –[no-]Allow-shlib-undefined-Option.

Normalerweise generiert der Linker eine Fehlermeldung für jedes gemeldete nicht aufgelöste Symbol, aber die Option –warn-unresolved-symbols kann dies in eine Warnung ändern.

  • Wofür sind die Äquivalente clang?

    – Igagis

    19. April 2021 um 0:43 Uhr

TL;DR Es kann nicht klagen, sondern du nicht will das. Ihr Code stürzt ab, wenn Sie den Linker zwingen, das Problem zu ignorieren. Es wäre kontraproduktiv.

Ihr Code stützt sich auf das alte C (vor C99), das es ermöglicht, Funktionen an ihrem Verwendungsort implizit zu deklarieren. Ihr Code ist semantisch äquivalent zu folgendem Code:

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

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

Der Linker beschwert sich zu Recht, dass die Objektdatei, die die kompilierte enthält function() bezieht sich auf ein Symbol, das nirgendwo anders gefunden wurde. Sie müssen es beheben Bereitstellung der Umsetzung zum made_up_function_name() oder durch Entfernen des unsinnigen Anrufs. Das ist alles, was dazu gehört. Kein Linker-Gefummel.

  • Wenn Sie jedoch eine gemeinsam genutzte Bibliothek erstellen, ist dies sinnvoll.

    – Topologische Sortierung

    11. Februar 2019 um 13:51 Uhr

  • Es macht überhaupt keinen Sinn: Symbole, die Sie importieren möchten, sind nicht undefiniert, sie sind nur dynamisch gebunden. Ich bezweifle sehr, dass Sie es tatsächlich ausprobiert haben und ein echtes Szenario bereitstellen können – denken Sie an eine Reihe von Bash-Befehlen, die die Quellen erstellen, kompilieren und verknüpfen und die Binärdateien ausgeben und diese zum Zeitpunkt des Links undefiniert demonstrieren Symbole.

    – Kuba hat Monica nicht vergessen

    11. Februar 2019 um 13:54 Uhr

  • Seien wir bürgerlich. Also: Wir haben Bibliotheken, die zusammenarbeiten: Sagen wir SDL2 und die Add-On-Bibliotheken SDL2_ttf, SDL2_image und SDL2_mixer. Müssen alle Add-Ons in SDL2 verlinkt werden? Würde das nicht ein Programm ergeben, das alle 4 dieser Bibliotheken verknüpft, 4 Kopien der Funktionen in SDL2?

    – Topologische Sortierung

    11. Februar 2019 um 14:51 Uhr

  • Überhaupt nicht, und es würde nicht mehrere Kopien erhalten, egal ob die Bibliotheken statisch oder dynamisch in die resultierende ausführbare Datei gelinkt wurden, mit der einzigen Einschränkung, dass, wenn die Add-Ons dynamisch mit SDL2 gelinkt wurden, SDL2 jedoch nicht dynamisch mit dem gelinkt wurde ausführbare Datei, dann müsste die ausführbare Datei selbst die Symbole von SDL2 exportieren. Dies ist sowohl in PE als auch in ELF möglich, und obwohl es möglicherweise nicht sehr beliebt ist, gibt es gültige Anwendungsfälle dafür. Angenommen, Sie packen Python ein und möchten es statisch verknüpfen, möchten aber trotzdem, dass die Benutzer ihre eigenen Python C-Module zu Ihrer Anwendung hinzufügen können.

    – Kuba hat Monica nicht vergessen

    11. Februar 2019 um 17:26 Uhr


  • Ein Vorbehalt ist, dass, wenn SDL2_foo gemeinsam genutzte Module sind und statisch mit SDL2 verknüpft sind, jedes seine eigene Kopie von SDL2 enthält, und das wollen wir natürlich nicht.

    – Kuba hat Monica nicht vergessen

    11. Februar 2019 um 17:32 Uhr

Wenn Sie den Prototyp der Funktion deklarieren, bevor Sie sie verwenden, soll sie kompiliert werden. Trotzdem bleibt der Fehler beim Verlinken bestehen.

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

  • Bearbeitete Frage, um dies widerzuspiegeln: Es gibt absolut keine andere Erwähnung der erfundenen Funktion als die im Beispiel gezeigte Anrufleitung.

    – STenjaK

    5. April 2011 um 17:19 Uhr

Benutzeravatar von Tim Williscroft
Tim Williscroft

Und dann ist da noch diese Gemeinheit mit dem an GCC übergebenen -D-Flag.

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


int main(){
}

$gcc undefined.c -Dmade_up_function_name=atexit
$

Stellen Sie sich vor, Sie suchen nach der Definition von made_up_function_name – sie erscheint noch nirgendwo im Code „erledigt“. Ich kann mir keinen guten Grund vorstellen, genau das im Code zu tun.

Das Flag -D ist ein mächtiges Werkzeug zum Ändern von Code zur Kompilierzeit.

Benutzeravatar von Sjors Telgen
Sjörs Telgen

Wenn Sie mit dem Linker-Flag erstellen -r oder --relocatable es wird auch keine “undefinierte Referenz”-Link-Fehlermeldung erzeugen.

Das ist weil -r verknüpft verschiedene Objekte in einer neuen Objektdatei, die später verknüpft werden soll.

Benutzeravatar von Bo Persson
Bo Persson

Wenn function() nie aufgerufen wird, ist sie möglicherweise nicht in der ausführbaren Datei enthalten, und die von ihr aufgerufene Funktion wird auch nicht gesucht.

Benutzeravatar der Community
Gemeinschaft

Der “Standard”-Algorithmus, nach dem POSIX-Linker arbeiten, lässt die Möglichkeit offen, dass der Code fehlerfrei kompiliert und verlinkt wird. Siehe hier für Details: https://stackoverflow.com/a/11894098/187690

Um diese Möglichkeit auszunutzen, muss die Objektdatei, die Ihre enthält function (nennen wir es f.o) sollte in einer Bibliothek abgelegt werden. Diese Bibliothek sollte in der Befehlszeile des Compilers (und/oder Linkers) erwähnt werden, aber zu diesem Zeitpunkt sollte keine andere Objektdatei (die zuvor in der Befehlszeile erwähnt wurde) Aufrufe an sie vorgenommen haben function oder jede andere Funktion, die in vorhanden ist f.o. Unter solchen Umständen sieht der Linker keinen Grund zum Abrufen f.o aus der Bibliothek. Linker wird vollständig ignorieren f.okomplett ignorieren function und bleiben daher völlig blind gegenüber dem Aufruf an made_up_function_name. Der Code wird trotzdem kompiliert made_up_function_name ist nirgendwo definiert.

1414280cookie-checkKann sich GCC nicht über undefinierte Referenzen beschweren?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy