外部符号是如何解决的?

sjs*_*sam 10 c++ g++ unix-ar static-linking nm

我有两个文件37064544_p1.cpp,37064544_p2.cpp内容相同,如下所示:

int add(int x,int y)
{
return x+y;
}
Run Code Online (Sandbox Code Playgroud)

我用它们编译了它们

g++ -c 37064544_p2.cpp -o 37064544_p2.o
g++ -c 37064544_p2.cpp -o 37064544_p2.o
Run Code Online (Sandbox Code Playgroud)

并使用将它们添加到存档中

ar -rsc lib37064544pf.a 37064544_p1.o 37064544_p2.o
Run Code Online (Sandbox Code Playgroud)

$ nm -s lib37064544pf.a 
Run Code Online (Sandbox Code Playgroud)

给我 :

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

37064544_p1.o:
0000000000000000 T _Z3addii

37064544_p2.o:
0000000000000000 T _Z3addii
Run Code Online (Sandbox Code Playgroud)

$ ar -t lib37064544pf.a 
Run Code Online (Sandbox Code Playgroud)

给我

37064544_p1.o
37064544_p2.o
Run Code Online (Sandbox Code Playgroud)

我有一个驱动程序,它调用_Z3addii编译的函数

g++ -static 37064544driver.cpp -o 37064544driver.elf -L. -l37064544pf
Run Code Online (Sandbox Code Playgroud)

结果是

Sum : 11
Run Code Online (Sandbox Code Playgroud)

问题

  1. 符号是如何_Z3addii解决的?

    • 是根据档案索引吗?
    • 它是否根据我们使用填充存档的顺序ar
  2. 我该如何更改此订单?

  3. 如何防止ar重复符号?

编译器: g ++ 4.6.3

use*_*267 2

符号_Z3addii是如何解析的?

实现可以自由地做任何它喜欢做的事,你违反了单一定义规则

实际上,它会在第一次匹配后停止寻找任何给定的符号,这可能遵循文件插入存档的顺序。

我如何更改此订单?

虽然ar您可以在插入目标文件时使用a(after) 和b(before) 修饰符在存档中定位目标文件,但您仍然违反了 ODR。

如何防止 ar 有重复的符号?

据我所知,你不能,ar这是相对愚蠢的,并且有充分的理由,因为某些语言确实允许相同的符号,这就是为什么在链接到存档时没有任何错误(ODR 违规不需要诊断) 。

您可以强制ld读取整个存档

g++ -static 37064544driver.cpp -o 37064544driver.elf -L. \
-Wl,--whole-archive -l37064544pf -Wl,--no-whole-archive
Run Code Online (Sandbox Code Playgroud)

或者您可以进行部分链接而不是传统的存档,如果有任何重复项,则会出现错误

ld -r -o lib37064544pf.a 37064544_p1.o 37064544_p2.o
Run Code Online (Sandbox Code Playgroud)