gpt4 book ai didi

C++ 异常和 .eh_frame ELF 部分

转载 作者:行者123 更新时间:2023-11-28 06:02:14 25 4
gpt4 key购买 nike

是否是 .eh_frame ELF 部分的缺失或损坏导致我的 C++ 代码中的异常停止工作?之前成功捕获的任何异常现在调用 std::terminate()。

我的情况:

  1. 我的 zzz.so 共享库有 try-catch block :

    try {
    throw Exc();
    } catch (const Exc &e) {
    LOG("ok " << e.what());
    } catch (...) {
    LOG("all");
    }
  2. 加载 zzz.so 的可执行文件(使用 ldopen)。它调用了 zzz.so 中的一个函数

  3. zzz.so 中抛出的所有异常都在 zzz.so 中成功捕获并转储到我的日志文件中
  4. 还有一个 aaa.so 被加载到另一个二进制文件中。另一个 aaa.so 正在加载我的 zzz.so。
  5. zzz.so 中抛出的所有相同异常都会导致调用 std::terminate()。

这怎么可能?

更新

我不知道这怎么可能,但是 Clang 3.3(FreeBSD clang 版本 3.3 (tags/RELEASE_33/final 183502) 20130610)解决了这个问题。

最佳答案

How is that possible?

当抛出异常时,控制传递给 __cxa_throw 例程(通常在 libstdc++.so 中),然后由该例程负责查找 catch 子句并在此过程中调用析构函数,如果未找到 catch 则调用 std::terminate

那么答案很可能是第一个可执行文件(异常起作用的那个)使用能够解码库中的 .eh_framelibstdc++.so,而第二个应用程序(异常不起作用的应用程序),或者使用较旧(不兼容)的 libstdc++.so 版本,或者针对 libstdc++.a 的链接,或者其他一些东西这些行。

注意:引发异常的实际工作是由 libgcc_s.so.1 中的 _Unwind_RaiseException 完成的,因此即使两个应用程序都使用同样的libstdc++.so,他们可能还是使用了不同的libgcc

更新:

Will I benefit from static linking libstdc++ and libgcc into my .so library?

也许吧。 TL;DR:这很复杂。

有几点需要考虑:

  1. 在除 i386 以外的任何平台上,您必须使用 -fPIC< 构建您自己的 libstdc++.alibgcc.a 拷贝,然后才能将它们链接到您的 zzz.so。通常这些库是在没有 -fPIC 的情况下构建的,并且不能静态链接到任何 .so

  2. libstdc++.a 静态链接到您的 zzz.so 可能使其成为派生作品,并受 GPL (请咨询您的律师)。

  3. 即使从 zzz.so 导出了一个 _Unwind_RaiseException,通常也已经有另一个 _Unwind_RaiseException 实例定义(较早加载)libgcc_s.so,并且较早的实例将被调用,从而使您的解决方法无效。为确保 您的 _Unwind_RaiseException 拷贝被调用,您需要将 zzz.so-Bsymbolic 链接起来,或使用特殊的链接器脚本在内部对 _Unwind_RaiseException(以及 libgcc.a 中的所有其他内容)进行所有调用。

  4. 您的变通方法可能会解决 zzz.so 的问题,但可能会导致不相关的 yyy.so 出现问题,它加载得更晚,并且需要系统提供的 _Unwind_RaiseException,而不是来自 zzz.so 的异常。这是隐藏所有 libgcc.a 符号并将它们置于 zzz.so 内部的另一个参数。

所以简短的回答是:这种变通办法可能会给您带来很多痛苦。

关于C++ 异常和 .eh_frame ELF 部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33035051/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com