带有动态加载库的未定义符号“typeinfo”

时间:2012-07-30 22:14:02

标签: c++

我正在尝试使用Linux上的gcc 4.6构建一个共享库,它是动态加载的。正如Web上的许多文章以及之前的问题所述,我在库中提供了c风格的工厂方法来创建和销毁对象。代码 - 以最小的形式 - 看起来像这样:

base.h:

class base {
public:
  base();
  virtual ~base();
  virtual int value() = 0;
};

base.cpp:

#include "base.h"
base::base() {}
base::~base() {}

main.cpp中:

#include "base.h"
#include <dlfcn.h>
#include <iostream>

int main() {
  void* handle = dlopen("liblib.so", RTLD_NOW);
  if(handle == NULL) std::cout << dlerror() << std::endl;

  // dlsym, ...
}

lib.cpp:

class derived : public base {
public:
  derived() {}
  virtual ~derived() {}
  virtual int value() { return 42; }
};

extern "C" derived* create_object() {
  return new derived();
}

编译好:

g++ -shared -fPIC lib.cpp -o liblib.so
g++ base.cpp main.cpp -ldl -o app

在运行时,由于缺少typeinfo符号

,它会崩溃
liblib.so: undefined symbol: _ZTI4base

在我之前发现的问题中,这个错误通常是由于某些错误“= 0;”或缺少虚拟功能的定义。但是在上面的例子中,base :: value是纯虚拟的,析构函数有一个定义。奇怪的是,nm报告_ZTI4base在app中定义:

$ nm app | grep _ZTI4base
0000000000601050 V _ZTI4base

那么为什么链接器不使用这个定义?

到目前为止,我发现使代码工作的唯一方法是在头文件中实现constructur和析构函数。然而,在执行此操作之后,base的相应符号在liblib.so中被nm报告并完全从app中消失,这可能意味着他们的定义被编译到库而不是app中,这不是我想要实现的。有没有人知道如何在不这样做的情况下完成上述工作?

1 个答案:

答案 0 :(得分:2)

链接程序时需要-rdynamic选项,导出其符号并使其可用于加载dlopen()的库。