二进制边界的例外

Säm*_*ämy 21 c++ exception-handling g++ shared-libraries

我知道,这个问题已被问过很多次,但我无法找到解决问题的方法.

我有以下情况:

   A
  / \
 /   \
B <-- C
Run Code Online (Sandbox Code Playgroud)
  • A是包含该类的共享库 EException
  • B和C链接A
  • C也是一个共享库
  • B在运行时动态加载C.

在某些时候,C抛出一个实例EException:

void doSometing() {
    throw EException("test-message");
}
Run Code Online (Sandbox Code Playgroud)

B我想抓住这个例外:

try {
    doSomething();
} catch (const EException& ex) {
    // Not reached
} catch (...) {
    // Not reached
}
Run Code Online (Sandbox Code Playgroud)

但正如代码中所提到的,没有一个catch子句被调用.相反,执行此代码的线程将被中止.

我尝试了以下事项:

  • EException编译A时,visibility属性设置为"default"
  • EException头文件只包含声明
  • -fvisibility=hidden在A,B和C中使用链接器选项
  • -E在C中使用链接器选项

使用nm我得到A:

0000000000066260 T EException::EException(QString const&)
0000000000066306 T EException::EException(EException const&)
00000000000661d0 T EException::EException() 
0000000000066260 T EException::EException(QString const&) 
0000000000066306 T EException::EException(EException const&) 
00000000000661d0 T EException::EException() 
00000000000664de T EException::~EException()
000000000006641e T EException::~EException() 
000000000006641e T EException::~EException() 
00000000000663b6 T EException::operator=(EException const&)
<...>
000000000028de40 V typeinfo for EException
000000000028dd80 V typeinfo for EException*
000000000007342b V typeinfo name for EException
0000000000072ab7 V typeinfo name for EException*
000000000028de00 V vtable for EException
Run Code Online (Sandbox Code Playgroud)

用于B:

U EException::EException(QString const&)
U EException::~EException()
<...>
0000000000726f60 V typeinfo for EException
Run Code Online (Sandbox Code Playgroud)

并为C:

U EException::EException(QString const&)
U EException::~EException()
<...>
U typeinfo for EException
Run Code Online (Sandbox Code Playgroud)

问题是,B使用自己的typeinfo EException,同时C使用提供的那个A?我该如何解决这个问题?

我的环境:

  • x86_64-linux-gnu上的gcc 4.6.3
  • 使用Qt

谢谢您的帮助!

小智 0

B 使用它自己的 EException 类定义V typeinfo for EException,而 C 似乎使用未解析的类定义( U 表示该类型在当前翻译单元中未定义,必须由加载器和动态链接器解析)。

验证 B 仍然是一个共享库,并且它不是与 A 静态链接,而是动态链接,防止 C 查找 A 的内容,因为我看不到 B 不会链接与 A 相同的类型。照顾好你的标头 ^^。