Как разрешаются внешние символы?

У меня есть два файла 37064544_p1.cpp и 37064544_p2.cpp с тем же содержимым, что показано ниже:

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

Я скомпилировал их, используя

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

и добавили их в архив с помощью

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

И

$ nm -s lib37064544pf.a 

дает мне:

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

37064544_p1.o:
0000000000000000 T _Z3addii

37064544_p2.o:
0000000000000000 T _Z3addii

и

$ ar -t lib37064544pf.a 

дает мне

37064544_p1.o
37064544_p2.o

У меня есть драйвер, который вызывает функцию _Z3addii, которая скомпилирована с помощью

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

Результат

Sum : 11

Вопросы

  • Как разрешен символ _Z3addii?

    • Это согласно индексу архива?
    • Это порядок, в котором мы заполняем архив, используя ar?
  • Как я могу изменить этот порядок?

  • Как предотвратить ar от дублирования символов?

Компилятор: g++ 4.6.3

Ответ 1

Как разрешен символ _Z3addii?

Реализация свободна делать все, что угодно, вы нарушаете одно правило определения.

Реально она перестанет искать какой-либо символ после первого совпадения, который, по-видимому, следует за порядком, в который файлы были вставлены в архив.

Как я могу изменить этот порядок?

С помощью ar вы можете использовать модификаторы a (после) и b (до) для размещения объектных файлов в архиве при их вставке, однако вы все еще нарушаете ODR.

Как я могу предотвратить ar из дубликатов символов?

Вы не можете, насколько я знаю, ar относительно глупы и по уважительной причине, поскольку некоторые языки допускают одинаковые символы, поэтому у вас нет ошибок при связывании с архивом (без диагностики требуется для нарушений ODR).

Вы можете либо заставить ld читать весь архив

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

Или вы можете сделать частичную ссылку вместо традиционного архива, который даст вам ошибку, если есть дубликаты

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