链接.如何同时定义和定义符号?

Voi*_*oid 6 c++ linker

$ nm --demangle /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/libsupc++.a  | grep "__cxxabiv1::__class_type_info::~__class_type_info"
Run Code Online (Sandbox Code Playgroud)

给出以下输出:

0000000000000000 T __cxxabiv1::__class_type_info::~__class_type_info()
0000000000000000 T __cxxabiv1::__class_type_info::~__class_type_info()
0000000000000000 T __cxxabiv1::__class_type_info::~__class_type_info()
                 U __cxxabiv1::__class_type_info::~__class_type_info()
                 U __cxxabiv1::__class_type_info::~__class_type_info()
Run Code Online (Sandbox Code Playgroud)

那么,如何解释这个输出?

  1. 这是符号的多个定义(三个T) - 它可能是怎样的?为什么链接器生成这样的库违反ODR?什么目的?为什么他们都有相同(和奇怪)的地址(0000000000000000)?
  2. 同一个符号如何同时定义(T)和undefined(U)?

Wim*_*wis 4

静态库(归档文件.a)本质上是单个文件的集合.o(加上一些索引信息,以便链接器可以找到.o它需要的文件)。其中一些未定义的符号与定义它们的对象位于不同的对象中。如果你查看完整的输出,nm这一点就会变得很清楚。(或使用该-o标志nm。)

您拥有多个定义的符号的原因是这demangle不是一对一的操作。在我的副本中libsupc++,这三个定义是:

0000000000000000 T _ZN10__cxxabiv117__class_type_infoD0Ev
0000000000000000 T _ZN10__cxxabiv117__class_type_infoD1Ev
0000000000000000 T _ZN10__cxxabiv117__class_type_infoD2Ev
Run Code Online (Sandbox Code Playgroud)

为什么有几个符号都被析构函数解构了?它们是针对不同情况的析构函数。gcc 使用用于 C++ 的 Itanium ABI,其名称修改规则如下所述。