2016-06-09 2 views
1

Ich habe den folgenden Code:Wie beschwört mein Projekt nicht ungelöste Unpünktlichkeiten, wenn Sie nicht dazu aufgefordert werden?

#include <iostream> 

extern "C" int calcSum_(int a, int b, int c); 

int main() 
{ 
    printf("Hello World"); 
    return 1; 
} 

Warum wird der folgende Code Build gewährt, dass ich keine anderen Quelldateien in meinem Projekt mit einer calcSum_ Funktion in ihnen haben? Es beschwert sich, wenn ich Folgendes versuche:

Baut nicht die Erstellung einer ausführbaren Datei, die ausgeführt werden kann? Bedeutet das nicht das Verknüpfen? Wie kann es ohne Fehler bauen? Warum muss ich meinen Linker "hervorheben", dass die Funktion fehlt?

+9

Wenn Sie die Funktion nie aufrufen, warum sollte der Linker sich darum kümmern, danach zu suchen? –

+3

Uh, vielleicht weil 'calcSum_()! = CalcSum()' (Unterstrich beachten)? – paulsm4

+0

@ paulsm4 mein schlechtes. Ich bearbeite das Hinzufügen der Unterstreichung – Bula

Antwort

2

Traditionell macht der Linker einen ziemlich niedrigen Job. Objektdateien enthalten eine Liste exportierter Symbole (zusammen mit ihrer Adresse) und eine Liste fehlender Symbole (zusammen mit den Adressen, an denen die aufgelöste Adresse innerhalb des Codes ersetzt werden muss). Der Linker muss sie alle zusammen nehmen, die fehlenden Symbole in den anderen Objektdateien finden und die Ersetzungen vornehmen.

Nun, wenn der Compiler einen Funktionsprototyp sieht, aber nicht verwendet wird, wird die Information nicht an den Linker weitergegeben - die Objektdatei benötigt dieses Symbol nicht, es muss kein Ersatz stattfinden -, also der Linker kann nicht wissen, dass eine Funktion deklariert, aber nicht definiert wurde.

Übrigens wurde dieses Verhalten in einigen C++ 03 Idiomen aktiv ausgenutzt - insbesondere der "deaktivierte Kopie Konstruktor"; Sie haben den Kopierkonstruktor so deklariert, dass er den automatisch generierten deaktiviert, aber Sie haben ihn nicht implementiert, sodass ein Verbindungsfehler ausgegeben wurde, falls jemand versehentlich versucht hat, ihn zu verwenden.

+0

Also wenn ich richtig verstehe, wenn jemand versucht, den Kopierkonstruktor zu verwenden, dann würde sich der Linker beschweren? (um die versehentliche Verwendung des Kopierkonstruktors zu verhindern? – Bula

+0

@Bula: genau (obwohl dies eine zweite Schutzlinie war, deklariert die erste Ebene einen solchen nicht-implementierten Konstruktor als privat, was eine bessere Rückmeldung über den Ort der fehlerhaften Verwendung gibt; der Linking-Teil war die versehentliche Verwendung durch die Klasse selbst zu vermeiden) –

+0

jede Möglichkeit, die Implementierung solcher Funktionen zu erzwingen? Ich nehme an, eine Checker-Funktion zu rufen und nicht die Rückkehr solcher Funktionen speichern? – Bula

0

In dem von Ihnen bereitgestellten Programm wird das Symbol calcSum_ nie referenziert, daher wird es vom Compiler niemals in Ihre Objektdatei (.o oder .obj) ausgegeben. Die einzige Abhängigkeit des Programms besteht in der Funktion printf (aus den C-Standard-Laufzeitbibliotheken)

Wenn der Linker ausgeführt wird, funktioniert es, Symbole in den Objektdateien zu verknüpfen. Das Symbol calcSum_ befindet sich nicht in der Objektdatei, daher muss der Linker es nicht verknüpfen, und Sie haben eine erfolgreich erstellte ausführbare Datei.

+0

Vielleicht sehr noobish Frage, aber es fängt an, die Symbole auszuarbeiten, die es benötigt, um von der Hauptfunktion hinunter zu seinem Rückkehrwert zu verbinden? – Bula

0

Die Linie:

extern "C" int calcSum_(int a, int b, int c); 

Teilt dem Compiler, der eine Funktion vorhanden ist und wie man es nennen. Nicht mehr, nicht weniger.

Wenn Sie die Funktion aufrufen, muss die Verbindung Phase finden, um es zu finden.

In Ihrem ersten Beispiel gibt es keinen Aufruf der Funktion, so dass der Linker sie nicht verwenden muss. Dies ist einer der Vorteile der C++ - Sprache, Sie zahlen nicht für das, was Sie nicht verwenden.

Im zweiten Beispiel rufen Sie die Funktion auf, also muss sie existieren.

+0

Ich habe an Java-Schnittstellen gedacht, bei denen Sie die in ihnen definierten Funktionen implementieren müssen. Wenn ich das richtig verstehe, geschieht die Verknüpfung nur zwischen den Dingen, die Sie im Code aufrufen. Sie können 20 nicht implementierte Funktionen haben? Ganz anders, wie würden Sie einen Fehler erzwingen, wenn die Funktionen nicht implementiert sind? (auch wenn nicht angerufen) – Bula

Verwandte Themen