使用libc++的Clang异常处理

7

我一直在尝试不同的C++库,并发现以下内容: 这是一个简单的应用:

#include <iostream>

int main(int argc, char* argv[])
{
    try
    {
        throw 1;
    }
    catch(...)
    {
        std::cout << "Exception is caught\n";
    }
}

当我在ARM上编译它时,就像这样:
clang++ -stdlib=stdlibc++

异常被如预期一样捕获了。
但是当我将其改为:
clang++ -stdlib=libc++

我经常收到以下信息:

terminating with uncaught exception of type int
Aborted

我尝试使用不同的标志明确地启用异常,例如:

-fexceptions
-fcxx-exceptions
-frtti

但是这些标志都无效。未捕获异常的原因是什么?可能是libc++安装不正确吗?

P.S. 在PC上,使用libc++编译的相同程序正常工作。 两个平台上libc++版本相同-3.7.0-1ubuntu0.1


如果是由于错误的libc++安装,你应该会收到某种链接器或加载器错误。我打赌libc++只支持在catch-all中的标准异常。 - hoodaticus
1
那为什么它在PC上能运行?而且通常的std::exception也没有被捕获。 - unresolved_external
也许clang生成异常管理代码时假定它将与错误的取消链接库链接!??尝试在生成的可执行文件上运行ldd。通常它会链接到libgcc_s,该库提供_Unwind_x符号的GCC版本。也许还要检查nm a.out | grep _Unwind。可能会出现有关预期符号版本的信息,例如在x86上的“@@@GCC_3.0”。但我想知道链接阶段怎么可能成功呢。 - Oliv
2个回答

7
是的,我遇到了与PowerPC、ARM以及X86 Linux本身完全相同的问题。问题是(我用PowerPC进行了跟踪):throw使用__cxa_throw,它调用libc++中libunwind部分的_Unwind_RaiseException。_Unwind_RaiseException本身通过".eh_frame"在ELF文件中向后查找调用函数。但是由于UnwindLevel1.c是一个C文件,在汇编部分中没有创建.eh_frame信息的.cfi_start ...信息。这意味着堆栈跟踪直接结束在第一个函数(_Unwind_RaiseException),而不是继续向后查找以识别调用的“catch”部分。这可以通过使用C++编译器(clang++而不是clang)编译libc++的.c部分来纠正。对于这种情况,也会为函数生成.cfi_start信息。现在,堆栈跟踪可以找到第一个函数以及之前的函数,一直追溯到主函数(在我的测试案例中)。对于ARM,我现在正在寻找下一个问题,因为堆栈跟踪不起作用。它一遍又一遍地扫描相同的函数,但不向后走(无限循环)。
当使用clang++编译.c文件时,你将遇到stdlib.h中未定义的部分的问题,因为它使用libcxx/include中错误的stdlib.h,而不是MUSL includes中的stdlib.h。我目前没有一个好的解决方案,除了手动修改一些头文件。
Kei

所有这些听起来都像是一个应该报告给libc++维护者的bug。 - Sebastian Redl
我的错误是在ARM上出现了无限循环,是因为代码中没有添加“展开信息”。这是因为我的目标没有被检测为EABI,因此编译器没有将.save .setfp .pad指令创建到汇编代码中。 - Kei
@Kei,你能否提供一下你构建lib的安装说明? - unresolved_external

1
这是由于libunwind编译中的一个错误。现在已经修复:https://reviews.llvm.org/D71117 当使用libc++和libunwind时,ARM上的异常会出现问题。据我所知,在LLVM-10.0.0中已经修复了这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接