链接器。如何同时定义和取消定义符号?

Linker. How could symbol be defined and undefined simultaneously?

$ nm --demangle /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/libsupc++.a  | grep "__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()
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()

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

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

静态库(存档文件,.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

为什么有几个符号都demangle到析构函数?他们是 destructors for different situations. gcc uses the Itanium ABI for C++, whose name mangling rules are described here.