2016-06-16 21 views
5

W projekcie statycznej biblioteki mam plik nagłówkowy z zadeklarowanymi, ale nie zaimplementowanymi funkcjami.Dlaczego to nie tworzy wielu zdefiniowanych symboli w tej bibliotece statycznej?

Mam plik .cpp, który implementuje te funkcje.

Następnie, aby lepiej zrozumieć błędy linkerów, skopiowałem plik cpp, więc mam jego dokładny duplikat, który również zostanie skompilowany. Tak więc oba pliki mają podwójne implementacje dla każdego symbolu w nagłówku.

Kompiluje, a gdy jest używany w innym projekcie, łączy.

Tutaj minimalny przykład dla biblioteki statycznej:

api.hpp:

void printWhatever(); 

errortest.cpp i duplicate.cpp są identyczne:

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

skompilować to jako statyczny biblioteka z tymi 2 plikami źródłowymi. Widzę, że kompilator generuje raporty dla obu plików.

Teraz używam tego skompilowaną bibliotekę w pliku wykonywalnego, inny projekt: main.cpp:

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

    return 0; 
} 

To działa i drukuje "hi".

Dlaczego nie ma wielu definicji tej funkcji?

+0

powinieneś dostać ten błąd na * etapie łączenia *, a nie podczas kompilowania –

+0

@ m.s. dzięki i poprawiłem pytanie –

+0

czy faktycznie łączysz dwa pliki obiektów razem? –

Odpowiedz

8

Kluczowym faktem, który został dodany do tej kwestii jest fakt, że te dwa moduły z duplikatu symbolu zostały połączone w statycznej biblioteki.

Biblioteka statyczna działa inaczej niż biblioteka współdzielona. Podczas łączenia linker przeszukuje biblioteki statyczne pod kątem przywoływanych symboli. Pierwszy moduł, który definiuje odnośnikowy symbol, zostaje połączony w celu utworzenia końcowego pliku wykonywalnego. Fakt, że inny moduł definiuje ten sam symbol, jest nieistotny. Jeśli drugi moduł z duplikatem nie definiuje żadnego innego symbolu wymaganego przez plik wykonywalny, nie jest połączony z plikiem wykonywalnym.

Jeśli chcesz zobaczyć duplikat błąd z bibliotek statycznych:

połączenia foo() i bar() ze swojego main().

Zdefiniuj foo() i baz() w 1. module w bibliotece statycznej.

Definicja bar() i baz() w drugim module w bibliotece statycznej.

Ponieważ oba moduły zawierają symbole, do których odwołuje się main(), są zmuszane do uzyskania połączenia z plikiem wykonywalnym, powodując powielenie błędu symbolu z powodu baz().

+0

'Pierwszy moduł, który definiuje odnośnik, zostaje połączony" - czy jest to arbitralne co do tego, który z nich może być? –

+0

Tak, kolejność modułów w bibliotece statycznej jest całkowicie dowolna. Zwykle każdy moduł eksportuje wiele symboli, a łącznik, próbując znaleźć każdy symbol używany przez główny plik wykonywalny, wyszukałby je w jakiejś nieokreślonej kolejności, co może spowodować, że którykolwiek z modułów zostanie najpierw połączony z plikiem wykonywalnym. –

2

W poniższym przykładzie wytwarza się wymaganą wartość łączącej:

main.cpp

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

file1.cpp

int demo() { return 1; } 

file2.cpp

int demo() { return 2; } 

skompilować

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

zaktualizowałem moje pytanie –

+0

Dodałem bounty na to pytanie, aby uzyskać bardziej szczegółową odpowiedź na moje zaktualizowane szczegóły. –

3

How to create a multiple defined symbols linking error

Dość minimalny program Shell wygenerować dość minimalny program w C źle sformułowane ++, który narusza jedną regułę definicji:

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

Powinno łatwo śledzić, co się dzieje. Istnieją dwa pliki źródłowe, które definiują nieliniową funkcję int main(), naruszając w ten sposób odr.

+0

Zaktualizowałem moje pytanie. Być może zasady wielu definicji różnią się w przypadku bibliotek statycznych? –

+0

@JXB przeczytać komentarze do pytania. Stwórz [mcve], która łączy pomyślnie, ale nie spodziewasz się. – user2079303

+0

zrobione, dzięki. krótki przykład. –

Powiązane problemy