为什么在这种情况下g ++不支持一个定义规则(ODR)? 。

时间:2014-07-30 16:22:16

标签: c++ header linker g++ redefinition

如您所见,链接时有多个testfn符号定义,但链接器首次出现(按链接顺序)并忽略其他库中的其他出现。 这可能是链接器的工作方式。

但有没有办法强制链接器在看到不同链接库中的多个符号时标记错误?或者任何其他选项来捕获这样的重复定义?


test1.h的内容:

#ifndef TEST1
#define TEST1
void testfn();
#endif

test1.cpp的内容

#include "test1.h"
#include <iostream>
using namespace std;
void testfn()
{
cout << "file1" << endl;
}

test.h的内容:

#ifndef TEST
#define TEST
void testfn();
#endif

test.cpp的内容:

#include "test.h"
#include <iostream>
using namespace std;
void testfn()
{
cout << "file" << endl;
}

main.cpp的内容:

#include "test.h"
#include "test1.h"

int main()
{
testfn();
return 0;

}

创建了一个共享库。

 g++ -fPIC -shared libtest1.so test1.cpp
 g++ -fPIC -shared libtest.so test.cpp

使用库顺序#1

创建可执行文件
g++ -o main main.cpp -ltest -ltest1

使用库订单#2

创建可执行文件
g++ -o main1 main.cpp -ltest1 -ltest

主要的输出

./main
file

main1的输出

 ./main1
file1

2 个答案:

答案 0 :(得分:2)

首先, 表示尊重ODR,只需从库中取出其中一种方法即可。这就是共享库的工作方式。

如果您希望看到编译器抱怨这一点,请将它们全部链接在一起,而不使用库步骤。

g++ -o main1 main.cpp test1.cpp test.cpp

所以你的问题变成了,“我怎么知道我是否有两个包含同名的标识符的库?”请记住,这通常不是问题,有时是故意做的。我建议运行库工具(我不熟悉g ++工具集)来获取库的列表,并运行它们的DIFF。

答案 1 :(得分:0)

我没有看到让GNU ld抱怨跨共享库的多个符号定义的方法。但是,如果涉及正常的静态库存档,您可以使用--whole-archive / --no-whole-archive选项集来获得所需内容:

例如,在构建libtest.alibtest1.a而不是共享库版本之后,我没有使用以下链接命令出错:

$ g++  -o main main.cpp   -ltest1 -ltest  -L.
$ ./main
file1

$ g++  -o main main.cpp   -ltest -ltest1  -L.
$ ./main
file

但是会出现以下错误:

$ g++  -o main main.cpp -Wl,--whole-archive -ltest1 -ltest -Wl,--no-whole-archive -L.
./libtest.a(test.o): In function `testfn()':
test.cpp:(.text+0x0): multiple definition of `testfn()'
./libtest1.a(test1.o):test1.cpp:(.text+0x0): first defined here
collect2: ld returned 1 exit status

我不确定您是否希望将--whole-archive用于发布版本 - 可能仅作为可能名称冲突的健全性检查(我认为使用--whole-archive通常会增加没有充分理由你的二进制文件。)

另外,如前所述,这似乎对共享库没有影响。