我理解在链接期间对象排序非常重要。在尝试让ld解决所有符号之前,我遇到了很多麻烦。这次ld没有产生任何错误,但输出错误!
项目很大(50K + C ++行)我无法生成简化版本,因此我将尝试描述我遇到的内容。希望有些专家能帮助我弄明白。
g++ -o bad.out a.o b.o ... x.so y.so
g++ -o good.out a.o b.o ... y.so x.so
虽然good.out运行正常,但bad.out却没有。 x.so和y.so都是由独立供应商提供的,因此它们的排序无关紧要。以下是更多线索:
不正确的行为表现为函数OnRspLogin()从未回调过。这是在y.so中定义的纯虚函数,在b.o中实现。 “grep OnRspLogin * .o * .so”仅在y.so和b.o中找到匹配。
显然ld没有将OnRspLogin()解析为b.o中的那个,但是哪一个解决了?这让我担心,因为链接器没有产生任何错误或警告。
我在CentOS 6.5上使用gcc 4.4.7-4。
修改 我发现x.so和y.so都包含一些常见的符号(例如T TcpClient),所以我猜在解析b.o:TcpClient时链接器选择了x.so:TcpClient(而不是y.so:TcpClient)。虽然更改.so命令可能会解决此问题,但我担心链接器可能会错误地解析a.o中的其他一些符号。那么有没有告诉链接器只使用y.so来解析b.o?请注意,这些.so文件由第三方提供,我无法更改它们。
答案 0 :(得分:1)
我发现x.so和y.so都包含一些常见的符号(例如T TcpClient)
是个问题。如果这些符号应该是不同的,那么可以将这两个库链接在一起 - 它们不是链接兼容的。
供应商解决这些问题的通常的方式是,他们在所有导出的符号(例如vendorA_TcpClient
)上使用不同的特定于供应商的前缀,并隐藏所有其他符号。
请注意,这些.so文件由第三方提供,我无法更改。
您可以告诉供应商您不能使用他们的库,除非他们避免定义没有前缀为其唯一标识符的符号,并且除非他们解决了这个问题,否则您不会支付它们。这样做时,供应商通常会变得非常敏感。