【问题标题】:Multiple symbol definitions and static libraries多个符号定义和静态库
【发布时间】:2018-05-11 12:54:52
【问题描述】:

我在链接过程中遇到了一个有点意外的行为,我想要求澄清一下。

似乎链接到一个目标文件和一个包含相同符号集的静态库是不等价的。前者导致multiple definition 错误,而后者似乎链接正确。

小例子

文件a.cb.c是一样的:

void myfunc() {
}

文件c.c是“主要”:

void myfunc();

int main()
{
    myfunc();
    return -1;
}

编译链接工作流程如下:

$ gcc -c a.c b.c c.c
$ gcc c.o a.o b.o   # Breaks!
a.o: In function `myfunc':
a.c:(.text+0x0): multiple definition of `myfunc'
b.o:b.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
$ ar rvs libb.a b.o
$ gcc c.o a.o -L./ -lb  # Works fine?

我的问题是:如果对象和静态库中包含的符号相同,为什么允许第二次链接而第一次不允许?

另外,这种行为是编译器还是系统特定的?

扩展

这可能是一个单独的问题,但将其放在此处可能很有用。如果在b.c 文件(例如对于 b.c 包含

void myfunc() {
}
void anotherfunc() {
}

现在链接步骤中断并出现与以前相同的错误:

gcc b.c 
gcc -L./ c.o -lb  a.o 
a.o: In function `myfunc':
a.c:(.text+0x0): multiple definition of `myfunc'
.//libb.a(b.o):b.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit stat

【问题讨论】:

    标签: c compilation linker linker-errors


    【解决方案1】:

    库只是目标文件的集合。没有检查多个定义。

    一个可执行文件只能有一个函数定义。在链接过程中,链接器修复对象中函数的调用(地址)。如果它遇到相同函数(名称)的第二个定义,它不知道使用哪一个。

    请注意,在静态库中有多个定义通常也会导致链接器抱怨多个定义,因为它不知道要使用库的哪个对象。在多个库中有多个定义可以通过给链接器一个库的顺序来解决:它将使用它遇到的第一个符号。

    【讨论】:

    • 抱歉,我不确定我是否理解您的回复。你能发展你的第一段吗?我的问题是关于链接静态库和目标文件。在我看来,在链接过程中不会发生对多个定义的检查。
    【解决方案2】:

    链接器仅在尚未找到定义时才在存档中查找定义。就你而言,
    $ gcc c.o a.o -L./ -lb # Works fine?
    有效,因为链接器已经在 a.c. 中找到了 myfunc() 的定义。对此的快速测试是在 a.c 和 b.c 中包含打印,以检查在运行可执行文件时使用了哪个 myfunc()。更多信息here.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-18
      • 2016-09-20
      相关资源
      最近更新 更多