"typeinfo" 符号未从动态库中导出

"typeinfo" symbols not exported from dynamic library

我无法 link 反对定义了一组我需要使用的 classes 的动态库。我的编译代码尝试 link 反对 class 的类型信息结构,但库未导出它。但是,class的虚table是。

使用 nm,我找到了我要解析的符号:

U __ZTIN3net14QuicSpdyStreamE

此 class 的动态库中唯一的特殊符号是:

S __ZTVN3net14QuicSpdyStreamE

我有两个问题:

背景

我正在尝试 link 反对 libnet.dylib 我通过 Chromium 的组件构建构建的。感兴趣的 class 是 QuicSpdyStream. All of its virtual functions are defined in quic_spdy_stream.cc. QuicSpdyStream itself is derived from QuicStream,它有一个纯虚函数 OnDataAvailable()

我的测试程序是这样的:

#include <iostream>

#include "base/macros.h"
#include "net/quic/core/quic_spdy_stream.h"
#include "net/quic/core/quic_types.h"

using namespace std;

class MyStream : public net::QuicSpdyStream {
 public:
  MyStream(net::QuicStreamId id, net::QuicSpdySession* session)
      : net::QuicSpdyStream(id, session){};

  void OnDataAvailable() override {};

 private:
  DISALLOW_COPY_AND_ASSIGN(MyStream);
};

int main(int argc, char** argv) {
  auto stream = new MyStream(net::QuicStreamId(1), NULL);
  cout << "Created stream with id:" << stream->id() << endl;
  return 0;
}

当我尝试构建时:

$ clang++ -I../externals/quic/src -I../externals/quic
-L../externals/libs -lnet -std=c++1y test.cpp 
Undefined symbols for architecture x86_64:   "typeinfo for net::QuicSpdyStream", referenced from:
typeinfo for net::MyStream in test-b130b2.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)

Chromium 本身附带一个玩具 quic_server,它以几乎相同的方式 here and here 使用此 class。当我构建一个组件构建时,关联的 quic_server 不依赖于 typeinfo 结构符号——这让我觉得我并不真的需要它。

我想知道这是否是 ABI 问题,因为 Chromium 库是在我的 Mac 上构建的,clang 版本为 7.0.0,我的系统版本是 LLVM 版本 9.0.0 (clang-900.0.39.2 ).

要解决此问题,您必须像禁用 RTTI 的 Chromium 一样编译代码,使用:-fno-rtti

Undefined symbols for architecture x86_64: "typeinfo for net::QuicSpdyStream", referenced from: typeinfo for net::MyStream

意味着编译器为您的 class MyStream 生成的 run-time 类型信息 (RTTI) 引用了其基础 class [=12= 缺少的类型信息].这是因为 Chromium 是在默认情况下禁用 RTTI 的情况下构建的[1]。

... Chromium builds without RTTI by default, but some sanitizers are known to require it, like CFI diagnostics and UBsan variants.

如果您愿意,也可以在 Chromium 配置中启用它(configurerttino_rtti)。

protobuf needs RTTI but has an define that allows to use it without it GOOGLE_PROTOBUF_NO_RTTI[2][3][4].