MacOS和Linux之间的C ++模板符号可见性差异?

时间:2017-07-23 20:09:10

标签: c++ linux macos linker elf

macOS和linux之间的可见性有哪些规则和规则差异 共享库中的内部/外部符号?特别是外在的 C ++模板实例化的可见性。看起来linux上的gcc允许链接到“未导出的”#39;符号....

示例:

如果我有一个带有虚函数的模板类" interface.h":

template <int T>
class SomeTemplate {
public:
  virtual void test_fun(void) const;
};

在库somelib.so中的私有源文件中定义了哪个函数 &#34; somelib.cpp&#34; (用g++ -fPIC -shared -o libsomelib.so somelib.cpp编译), 其中库还在其他函数/类方法中使用实例化模板:

#include <iostream>
#include "interface.h"

template <int T>
void SomeTemplate<T>::test_fun(void) const
{
  std::cout << "Test function " << T << std::endl;
}

void something(void)
{
  SomeTemplate<1>().test_fun();
}

// Explicit template instantiation required for macOS - see below
// template class SomeTemplate<1>;

在linux上编译时,模板符号最终会出现在&#34; W&#34;部分,如 由nm -C libsomelib.so | grep SomeTemplate确定:

0000000000000bc4 W SomeTemplate<1>::SomeTemplate()
0000000000000bc4 W SomeTemplate<1>::SomeTemplate()
0000000000000be0 W SomeTemplate<1>::test_fun() const
0000000000201060 V typeinfo for SomeTemplate<1>
0000000000000c90 V typeinfo name for SomeTemplate<1>
0000000000201040 V vtable for SomeTemplate<1>

在链接到这个somelib的程序/库中使用它可以很好地工作,例如&#34; program.cpp&#34; (g++ -o testlib libsomelib.so program.cpp):

#include "interface.h"

int main(int argc, char const *argv[])
{
  SomeTemplate<1>().test_fun();
  return 0;
}

但是,在macOS上进行编译(以及手动解码)会放置所需的符号 由man nm调用&#34;本地(非外部)文本部分的程序&#34;:

0000000000000f70 t SomeTemplate<1>::SomeTemplate()
0000000000000fe0 t SomeTemplate<1>::SomeTemplate()
0000000000000f90 t SomeTemplate<1>::test_fun() const
00000000000020d8 D typeinfo for SomeTemplate<1>
0000000000001f50 S typeinfo name for SomeTemplate<1>
00000000000020c0 d vtable for SomeTemplate<1>

所以它似乎是一个私有符号,程序的链接失败了未定义的符号:

Undefined symbols for architecture x86_64:
  "SomeTemplate<1>::test_fun() const"

似乎模板库中模板化类的使用不是 够 - 我需要明确声明模板实例化,例如 somelib.cpp中的注释行,然后符号最终显示在&#34; T&#34;,可见,测试程序编译并运行。

造成这种行为差异的原因是什么,我必须使用哪些术语来理解这一点,是否有办法让平台与行为相匹配?非显式实例化是否被认为是最终必然会破坏的不良实践?

(这是一个很大的项目,我加入了上游图书馆开发人员不一定要改变的地方,而我的前任显然放弃了,并且在编写macOS时强制所有内容都是静态链接。)

0 个答案:

没有答案