2016-06-16 14 views
5

In einem statischen Bibliotheksprojekt habe ich eine Headerdatei mit deklarierten, aber nicht implementierten Funktionen.Warum erstellt dies nicht mehrere definierte Symbole in dieser statischen Bibliothek?

Ich habe eine .cpp-Datei, die diese Funktionen implementiert.

Dann, um Linker Fehler besser zu verstehen, kopierte ich die CPP-Datei, so dass ich ein genaues Duplikat davon habe, das auch kompiliert wird. Daher haben beide Dateien doppelte Implementierungen für jedes Symbol im Header.

Es kompiliert, und wenn in einem anderen Projekt verwendet, verbindet es.

Hier ein Minimum Beispiel für statische Bibliothek:

api.hpp:

void printWhatever(); 

errortest.cpp und duplicate.cpp sind identisch:

#include "api.hpp" 
#include <iostream> 
void printWhatever(){ 
    std::cout << "hi " << "\n"; 
} 

ich kompilieren dies als statische Bibliothek mit diesen 2 Quelldateien. Ich sehe, dass der Compiler Berichte für beide Dateien erstellt.

Jetzt benutze ich diese kompilierte Bibliothek in einer ausführbaren Datei, ein anderes Projekt: main.cpp:

#include <api.hpp> 
int main(int argc, const char * argv[]) { 
    printWhatever(); 

    return 0; 
} 

Es läuft und druckt "hallo".

Warum gibt es keine Mehrfachdefinition für die Funktion?

+0

Sie sollten diesen Fehler bei der * Verknüpfungsstufe * erhalten, nicht beim Kompilieren –

+0

@ m.s. Danke, ich korrigierte die Frage –

+0

sind Sie tatsächlich verbinden die beiden Objektdateien zusammen? –

Antwort

8

Der Schlüssel Tatsache, dass auf diese Frage hinzugefügt wurde, ist die Tatsache, dass die beiden Module mit dem doppelten Symbol in eine statische Bibliothek verbunden waren.

Eine statische Bibliothek funktioniert sehr anders als eine gemeinsam genutzte Bibliothek. Beim Linking durchsucht der Linker statische Bibliotheken nach referenzierten Symbolen. Das erste Modul, das das referenzierte Symbol definiert, wird verknüpft, um die endgültige ausführbare Datei zu erstellen. Die Tatsache, dass ein anderes Modul das gleiche Symbol definiert, ist irrelevant. Wenn das andere Modul mit dem Duplikatsymbol kein anderes Symbol definiert, das die ausführbare Datei benötigt, wird es nicht in die ausführbare Datei eingebunden.

Wenn Sie einen doppelten Fehler mit statischen Bibliotheken sehen möchten:

Anruf foo() und bar() von Ihrem main().

Definieren Sie foo() und baz() im ersten Modul in der statischen Bibliothek.

Definieren Sie bar() und baz() im zweiten Modul in der statischen Bibliothek.

Da beide Module Symbole enthalten, auf die von main() verwiesen wird, werden sie gezwungen, mit der ausführbaren Datei verbunden zu werden, was zu einem doppelten Symbolfehler aufgrund von baz() führt.

+0

'Das erste Modul, das das referenzierte Symbol definiert, wird verknüpft '- ist das beliebig, um welches es könnte? –

+0

Ja, die Reihenfolge der Module in einer statischen Bibliothek ist völlig willkürlich. Außerdem exportiert jedes Modul normalerweise mehrere Symbole, und der Linker sucht beim Suchen nach jedem Symbol, das von der Hauptdatei verwendet wird, in einer nicht angegebenen Reihenfolge, was dazu führen kann, dass eines der Module zuerst mit der ausführbaren Datei verknüpft wird. –

2

Das folgende Beispiel erzeugt die gewünschten Verknüpfungsfehler:

main.cpp

int demo(); 
int main() { return demo(); } 

file1.cpp

int demo() { return 1; } 

file2.cpp

int demo() { return 2; } 

g++ main.cpp file1.cpp file2.cpp 

/tmp/ccdzSL9x.o: In function demo()': file2.cpp:(.text+0x0): multiple definition of demo()' /tmp/cc7Hzvrb.o:file1.cpp:(.text+0x0): first defined here collect2: error: ld returned 1 exit status

+0

Ich habe meine Frage aktualisiert –

+0

Ich habe eine Prämie hinzugefügt zu dieser Frage, um eine spezifischere Antwort auf meine aktualisierten Details zu erhalten –

3

How to create a multiple defined symbols linking error

Ganz minimal Shell-Programm kompiliert ein ganz minimal schlecht gebildet C++ Programm zu erzeugen, die eine Definitionsregel verletzt:

echo 'int main(){}' | tee a.cpp > b.cpp 
g++ a.cpp b.cpp 

Es soll einfach zu verfolgen, was vor sich geht. Es gibt zwei Quelldateien, die beide eine Nicht-Inline-Funktion int main() definieren und dadurch odr verletzen.

+0

Ich habe meine Frage aktualisiert. Vielleicht sind die Regeln für die Mehrfachdefinition für statische Bibliotheken anders? –

+0

@JXB lesen Sie die Kommentare zu der Frage. Erstellen Sie eine [mcve], die erfolgreich verknüpft, aber Sie erwarten nicht. – user2079303

+0

fertig, danke. kurzes Beispiel. –