.eh_frame ELF部分的缺失或损坏是否导致我的C ++代码中的异常停止工作?之前成功捕获的任何异常现在都在调用std :: terminate()。
我的情况:
我的zzz.so共享库有try-catch块:
try {
throw Exc();
} catch (const Exc &e) {
LOG("ok " << e.what());
} catch (...) {
LOG("all");
}
加载zzz.so的可执行文件(使用ldopen)。它在zzz.so
这怎么可能?
更新
我不知道HOW怎么可能,但是Clang 3.3(FreeBSD clang version 3.3(标签/ RELEASE_33 / final 183502)20130610)解决了这个问题。
答案 0 :(得分:1)
这怎么可能?
当抛出异常时,控制传递给__cxa_throw
例程(通常在libstdc++.so
),然后负责查找catch
子句并沿途调用析构函数,std::terminate,则<或调用catch
。
那么答案很可能是第一个可执行文件(异常工作的那个)使用能够解码库中libstdc++.so
的{{1}},而第二个应用程序(例外的那个)不起作用),要么使用.eh_frame
的较旧(不兼容)版本,要么使用libstdc++.so
的链接,或者这些行中的某些内容。
注意:提升异常的实际工作由libstdc++.a
中的_Unwind_RaiseException
完成,因此即使两个应用程序都使用相同的libgcc_s.so.1
,它们也可能仍然使用不同的libstdc++.so
。
<强>更新强>
我是否可以将libstdc ++和libgcc静态链接到我的.so库中?
也许。 TL; DR:这很复杂。
有几件事需要考虑:
在i386以外的任何平台上,您必须使用libgcc
构建自己的libstdc++.a
和libgcc.a
副本,然后才能将它们链接到-fPIC
}。通常这些库是在没有zzz.so
的情况下构建的,并且不能静态链接到任何-fPIC
。
将.so
静态链接到libstdc++.a
中可以将其作为派生作品,并遵守GPL(咨询您的律师)。
即使从zzz.so
导出_Unwind_RaiseException
,通常也会在({之前加载的)zzz.so
中定义另一个_Unwind_RaiseException
实例,并且早期的实例是将要调用的实例,使您的解决方法无效。要确保调用您的 libgcc_s.so
副本,您需要将_Unwind_RaiseException
与zzz.so
相关联,或者使用特殊的链接描述来调用所有调用-Bsymbolic
(以及来自_Unwind_RaiseException
的所有内容)内部。
您的解决方法可能会解决libgcc.a
的问题,但可能会导致即使以后加载的无关zzz.so
出现问题,并且需要系统提供的yyy.so
,不是来自_Unwind_RaiseException
的那个。这是隐藏所有zzz.so
符号并使其成为libgcc.a
内部符号的另一个参数。
所以简短的回答是:这样的解决方法可能会给你带来很大的痛苦。