2016-05-06 31 views
10

Mam dwa pliki 37064544_p1.cpp & 37064544_p2.cpp o tej samej treści, jak pokazano poniżej:W jaki sposób są rozwiązywane symbole zewnętrzne?

int add(int x,int y) 
{ 
return x+y; 
} 

Skompilowałem je za pomocą

g++ -c 37064544_p2.cpp -o 37064544_p2.o 
g++ -c 37064544_p2.cpp -o 37064544_p2.o 

i dodaje je do archiwum z wykorzystaniem

ar -rsc lib37064544pf.a 37064544_p1.o 37064544_p2.o 

I

$ nm -s lib37064544pf.a 

daje mi:

Archive index: 
_Z3addii in 37064544_p1.o 
_Z3addii in 37064544_p2.o 

37064544_p1.o: 
0000000000000000 T _Z3addii 

37064544_p2.o: 
0000000000000000 T _Z3addii 

i

$ ar -t lib37064544pf.a 

daje mi

37064544_p1.o 
37064544_p2.o 

mam kierowca, który wywołuje funkcję _Z3addii który jest skompilowany z

g++ -static 37064544driver.cpp -o 37064544driver.elf -L. -l37064544pf 

Wynik jest

Sum : 11 

Pytania

  1. Jak jest symbol _Z3addii rozwiązany?

    • Czy jest według indeksu archiwum?
    • Czy jest to zgodne z kolejnością, w jakiej zapełniamy archiwum za pomocą ar?
  2. Jak mogę zmienić tę kolejność?

  3. Jak mogę zapobiec dodawaniu powtarzających się symboli przez ar?

Compiler: g ++ 4.6.3

+1

Hmmmm, właśnie próbowałem tego na klang. Jeśli skompilujesz z dwoma plikami .o bezpośrednio, otrzymasz duplikat błędu symbolu, ale jeśli umieścisz dwa pliki .o w pliku .a i skompilujesz je z tym, to nie ma błędu. Zawsze uważałem, że .a był po prostu wygodnym sposobem na zbieranie plików .o, ale wygląda na to, że jest pod pewnymi względami inny. – xaxxon

+1

Znacznik 'r' do ar wydaje się, że oznacza to, że rzeczy dodane do archiwum później zastąpią wcześniejsze, chociaż zamiast tego uruchomię je za pomocą q, nadal nie mogę uzyskać duplikatu błędu symbolu. Czy linker przestaje przeglądać pojedynczy plik, gdy napotyka pierwszy wpis dla symbolu, którego szuka? – xaxxon

+0

@xaxxon: 'Jeśli skompilujesz z dwoma plikami .o bezpośrednio, otrzymasz duplikat błędu symbolu,'. Tak, ale nie zawsze jestem za tym dla wygody – sjsam

Odpowiedz

2

Jak jest symbol _Z3addii rozwiązany?

Implementacja jest darmowa, aby zrobić cokolwiek zechcesz, naruszasz kod one definition rule.

Realistycznie przestanie wyszukiwać dowolny symbol po pierwszym dopasowaniu, co prawdopodobnie wynika z kolejności włożenia plików do archiwum.

Jak mogę zmienić tę kolejność?

Z ar można użyć a (po) i b (przed) modyfikatory do położenia plików obiektowych w archiwum przy wkładaniu ich, jesteś nadal naruszenie ODR chociaż.

Jak mogę zapobiec użyciu duplikatów symboli?

Nie można o ile mi wiadomo, ar jest stosunkowo głupi i nie bez powodu, ponieważ niektóre języki pozwalają na identycznych symboli, dlatego nie ma żadnych błędów podczas łączenia z archiwum (nie diagnostyka jest wymagana w przypadku naruszeń ODR).

Można siła ld czytać całego archiwum

g++ -static 37064544driver.cpp -o 37064544driver.elf -L. \ 
-Wl,--whole-archive -l37064544pf -Wl,--no-whole-archive 

Albo można zrobić częściowy odnośnik zamiast tradycyjnego archiwum, które dadzą Ci błąd, jeśli istnieją duplikaty

ld -r -o lib37064544pf.a 37064544_p1.o 37064544_p2.o 
+0

Dziękuję.Zgadzam się, że jestem naruszenie ODR.Ale było to celowo w odniesieniu do tego przykładu.Mniejsze zainteresowanie było jednak wykrywanie tego podczas archiwizowania kodu obiektu.Dziękujemy za punkt na częściowe łączenie. Rozważałbym także dodanie obiektów do różnych bibliotek i połączenie ich w żądanej kolejności. – sjsam