C++ 异常未在 clang 17.0.3 上捕获

C++ Exception not caught on clang 17.0.3

提问人:Balázs g 提问时间:10/27/2023 最后编辑:Balázs g 更新时间:10/28/2023 访问量:288

问:

这是我今天遇到的一个错误的简化版本。

#include <iostream>
#include <vector>
#include <stdexcept>

void run() {
    std::vector<int> v;
    throw std::runtime_error("error");
}

int main() {
    try {
        run();
    } catch (const std::exception &e) {
        std::cerr << e.what() << std::endl;
        return 1;
    }

    return 0;
}

我在 M1 Mac 上使用 Homebrew clang 版本 17.0.3 编译并运行了这段代码:

clang++ -std=c++20 -o main main.cpp

未捕获异常,程序退出时显示:

Process finished with exit code 133 (interrupted by signal 5: SIGTRAP)

如果我从 run 函数中删除或在 Linux 上编译它,那么它就可以工作了。std::vector<int> v;

编辑: 所以,我最初是使用 cmake 通过 CLion 编译的,它还添加了 .-L/opt/homebrew/opt/llvm/lib

我测试了它手动编译,结果:

# works
clang++ -std=c++20 -o main main.cpp

# crashes with c++11, c++17 and c++20
clang++ -std=c++20 -O0 -o main -L/opt/homebrew/opt/llvm/lib main.cpp

# works
clang++ -std=c++20 -O1 -o main -L/opt/homebrew/opt/llvm/lib main.cpp

生成的程序集文件:https://drive.google.com/drive/folders/13UKnC0mp6_3l_QULO62ts_UQHK1ZR23u?usp=share_link

我的猜测是 -O1 只是剥离了创建向量,因为添加更多代码以确保它被保留会导致陷阱。

在 中创建一个空类,该类具有打印某些内容的析构函数也会导致同样的问题。run()

C++ macOS 异常 叮当 C++20

评论

2赞 Jabberwocky 10/27/2023
您使用什么编译器标志?您是否尝试过一些不同的标志,例如 xxx 是 c++11、c++14、c++17、c++20 等和/或不同的优化级别?编辑问题并将所有详细信息放入问题中。-std=xxx
1赞 NathanOliver 10/27/2023
如果添加一个,该块会捕获异常吗?catch (...)
1赞 YSC 10/27/2023
你能分享一下你的编译器生成的程序集吗?这看起来像一个编译器错误(以消除您可能有的任何疑问)。如果行为与 不变,请同时提供两个程序集。-O2
1赞 Jabberwocky 10/27/2023
@Balázsg 你有没有尝试过一些不同的标志,比如等等?以及不同的优化级别,如 、 、 、 ?请编辑并将所有信息放入问题中。-std=c++-17-O0-O1-O2-O2
1赞 Jabberwocky 10/27/2023
令人惊讶的是,该版本有效,但该版本无效。您能否发布生成的汇编代码,用于一个有效的版本和一个以前不按要求使用的版本?但无论如何,这看起来更像是该选项的问题。-O1-O0-L/opt/homebrew/opt/llvm/lib

答:

4赞 Balázs g 10/28/2023 #1

这是一个配置错误。

摘录。brew info llvm

==> Caveats
To use the bundled libc++ please add the following LDFLAGS:
  LDFLAGS="-L/opt/homebrew/opt/llvm/lib/c++ -Wl,-rpath,/opt/homebrew/opt/llvm/lib/c++"

llvm is keg-only, which means it was not symlinked into /opt/homebrew,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

If you need to have llvm first in your PATH, run:
  echo 'export PATH="/opt/homebrew/opt/llvm/bin:$PATH"' >> ~/.zshrc

For compilers to find llvm you may need to set:
  export LDFLAGS="-L/opt/homebrew/opt/llvm/lib"
  export CPPFLAGS="-I/opt/homebrew/opt/llvm/include"

使用代码按预期运行。-L/opt/homebrew/opt/llvm/lib/c++

评论

0赞 Sebastian 11/9/2023
当我尝试使用 llvm 和异常处理进行编译时,我遇到了同样的问题。我还检查了 brew info llvm,按照说明(并按照您在此处的说明)似乎并不能为我解决问题......使用 -O1 还可以使代码正确运行。
0赞 Balázs g 11/9/2023
@Sebastian 您确定编译器不会删除导致 -O1 问题的代码吗?在我的测试中似乎就是这种情况。