如何在 M1 Mac 上捕获浮点异常?

2023-12-03

捕获浮点异常的方法取决于体系结构。这是我在 Intel (x86) Mac 上成功测试的代码:它两次取负数的平方根,一次在之前,一次在之后,从而启用浮点异常捕获。第二次,fpe_signal_handler()叫做。

#include <cmath>        // for sqrt()                                           
#include <csignal>      // for signal()                                         
#include <iostream>
#include <xmmintrin.h>  // for _mm_setcsr                                       

void fpe_signal_handler(int /*signal*/) {
  std::cerr << "Floating point exception!\n";
  exit(1);
}

void enable_floating_point_exceptions() {
 _mm_setcsr(_MM_MASK_MASK & ~_MM_MASK_INVALID);
 signal(SIGFPE, fpe_signal_handler);
}

int main() {
  const double x{-1.0};
  std::cout << sqrt(x) << "\n";
  enable_floating_point_exceptions();
  std::cout << sqrt(x) << "\n";
}

使用Xcode提供的apple-clang编译器进行编译

clang++ -g -std=c++17 -o fpe fpe.cpp

并运行给出以下预期输出:

nan
Floating point exception!

我想编写一个类似的程序,在 M1 (arm64) Mac 上执行与上述程序相同的操作。我尝试了以下方法:

#include <cfenv>        // for std::fenv_t                                      
#include <cmath>        // for sqrt()                                           
#include <csignal>      // for signal()                                         
#include <fenv.h>       // for fegetenv(), fesetenv()                           
#include <iostream>

void fpe_signal_handler(int /*signal*/) {
  std::cerr << "Floating point exception!\n";
  exit(1);
}

void enable_floating_point_exceptions() {
 std::fenv_t env;
 fegetenv(&env);
 env.__fpcr = env.__fpcr | __fpcr_trap_invalid;
 fesetenv(&env);
 signal(SIGFPE, fpe_signal_handler);
}

int main() {
  const double x{-1.0};
  std::cout << sqrt(x) << "\n";
  enable_floating_point_exceptions();
  std::cout << sqrt(x) << "\n";
}

它几乎可以工作:使用 Xcode 提供的 apple-clang 编译器编译后

clang++ -g -std=c++17 -o fpe fpe.cpp

我得到以下输出:

nan
zsh: illegal hardware instruction  ./fpe

我尝试添加-fexceptions标志,但这没有什么区别。我注意到ARM 编译器工具链“不支持 AArch64 目标的浮点异常捕获”,但我不确定这是否适用于带有 Apple 工具链的 M1 Mac。

我是否正确地认为 M1 Mac 硬件不支持浮点异常捕获?或者有没有办法修改这个程序,使其捕获第二个浮点异常,然后调用fpe_signal_handler()?


使用 ISO C 在同一线程内同步测试异常确实可以正常工作fetestexcept from <fenv.h> as in cppreference 示例。这里的问题是让 FP 异常真正捕获,以便操作系统提供SIGFPE,而不是仅仅在 FP 环境中设置粘性标志。


根据下面的长时间讨论(非常感谢 @Peter Cordes 的耐心),似乎在 Aarch64 上的 MacOS 上,揭露 FP 异常,然后在 SIGILL 而不是 SIGFPE 中生成相应的错误 FP 数学结果。可以在处理程序中检测到信号代码 ILL_ILLTRP。

#include <fenv.h>    
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

static void
fpe_signal_handler( int sig, siginfo_t *sip, void *scp )
{
    int fe_code = sip->si_code;

    printf("In signal handler : ");

    if (fe_code == ILL_ILLTRP)
        printf("Illegal trap detected\n");
    else
        printf("Code detected : %d\n",fe_code);

    abort();
}

void enable_floating_point_exceptions()
{
    fenv_t env;
    fegetenv(&env);

    env.__fpcr = env.__fpcr | __fpcr_trap_invalid;
    fesetenv(&env);

    struct sigaction act;
    act.sa_sigaction = fpe_signal_handler;
    sigemptyset (&act.sa_mask);
    act.sa_flags = SA_SIGINFO;
    sigaction(SIGILL, &act, NULL);
}

void main()
{
    const double x = -1;    
    printf("y = %f\n",sqrt(x));
    enable_floating_point_exceptions();
    printf("y = %f\n",sqrt(x));
}

这导致:

y = nan
In signal handler : Illegal trap detected
Abort trap: 6

其他浮点异常可以以类似的方式检测,例如取消屏蔽__fpcr_trap_divbyzero,然后生成double x=0; double y=1/x。如果异常未被屏蔽,则程序正常终止。

然而,如果没有 SIGFPE,似乎无法准确检测哪个浮点操作触发了信号处理程序。人们可以想象揭开所有异常(例如使用 FE_ALL_EXCEPT)。然后,当错误的数学运算生成 SIGILL 时,我们在处理程序中没有足够的信息来了解哪个操作发送了信号。揭露所有异常并进行一些尝试fetestexcept在处理程序中没有产生非常可靠的结果。这可能需要更多调查。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 M1 Mac 上捕获浮点异常? 的相关文章

随机推荐

  • 使用细粒度方法线程安全地删除链表节点

    为什么以下删除链表中节点的代码片段不是线程安全的 编辑 注意每个节点都有自己的锁 lock acquisition here assumption found to be valid here prev gt next p gt next
  • Excel - 根据条件创建查找值数组的公式

    我一直在寻找这个看似简单的问题的解决方案 但到目前为止失败了 我在 Excel 中有一个这样的表格 Column 1 Column 2 apples 1 apples 2 bananas 5 apples 3 bananas 4 我需要一个
  • 如何使用从 api 获取的 React 组件?

    我有一个 api 它为我提供了一个经过 Webpack 处理的 React 组件 如下所示 module exports function e var t function r n if t n return t n exports var
  • std::map,指向映射键值的指针,这可能吗?

    std map
  • 没有jquery的scrollTop动画[重复]

    这个问题在这里已经有答案了 我正在尝试在不使用 jQuery 的情况下制作动画 滚动到顶部 效果 在 jQuery 中 我通常使用以下代码 go to top click function html body animate scrollT
  • 为什么 Option 的大小等于 1?

    On 铁锈游乐场 大小Option
  • 调整动态平铺图像的大小 - WriteableBitmapEx

    找到了解决方案由于这是一个图块 因此图像将始终拉伸到 173 x 173 为了避免这种情况 首先创建一个 173 x 173 的虚拟模型 并将其与调整大小的虚拟模型合并 Rect rect new Rect 0 0 0 0 width he
  • 将 ImageView 放在 Button android 上

    我正在尝试使用RelativeLayout 将 ImageView 放置在 Button 上 这是我的 xml
  • 将(双字节)字符串转换为十六进制

    假设我有用西里尔字母写的 俄语 一词 这相当于以下十六进制 1056 1091 1089 1089 1082 1080 1081 我的问题是 如何编写一个函数 该函数将从西里尔字母中的 俄语 转换为上面的十六进制值 这个相同的函数也适用于单
  • ASP.NET WebForms 身份验证注销,Cookie 仍可用于访问网站

    我一直在用头撞墙并在网上搜索此内容 但我认为我在理解将用户从 ASP NET WebForms 应用程序中注销的整个过程方面遇到了问题 问题 我能够登录我的应用程序并且它使用 cookie 因此我在浏览器中设置了 cookie 这是配置表单
  • PHP intl.so 失败

    PHP 警告 PHP 启动 无法加载动态库 usr lib php extensions no debug non zts 20121212 intl so dlopen usr lib php extensions no debug no
  • 如何在 SQL Server 中循环访问一组记录?

    如何循环遍历一组记录select陈述 假设我有一些记录 我希望循环遍历并对每条记录执行一些操作 这是我的原始版本select陈述 select top 1000 from dbo table where StatusID 7 通过使用 T
  • 使用 moment.js 查找给定工作日(即星期一)的下一个实例

    我想获取下周一或周四的日期 或者今天 如果是周一或周四 由于 Moment js 在周日至周六的范围内工作 我必须计算出当前日期并据此计算下周一或周四 if moment format dddd Sunday var nextDay mom
  • 反序列化时的备用属性名称

    关于这个问题 使用 Json net 序列化时如何更改属性名称 当然 很好 但是我可以把蛋糕吃掉吗 我正在寻找一种令人赏心悦目的方式 为属性提供一个备用名称 使得字符串可以包含其中之一 就像是 BetterJsonProperty Prop
  • 来自 Dymola mos 脚本的 mkdir

    我有一个用于运行多个模拟的 mos 脚本 在运行模拟之前 我想cd to a new目录 以便保存所有结果和日志文件并且永远不会被覆盖 目前只能cd据我所知 到现有目录 任何人都建议如何创建名为例如的目录temp modelname and
  • 如何从Python中的URL获取域名(名称+TLD)

    我想从格式可能不同的 URL 列表中提取域名 网站名称 TLD 例如 当前状态 gt 我想要什么 mail yahoo com gt yahoo com account hotmail co uk gt hotmail co uk x it
  • 高优先级 Android 服务

    我正在考虑为 Android 实现一个基于蓝牙的视频流服务 我怎样才能确保 该服务以高优先级运行 我想最大限度地减少延迟 当内存紧张时 服务是要被杀死的东西列表中的低位吗 为了确保您的服务持续运行 您需要做两件重要的事情 确保你打电话sta
  • 使用按钮在具有参数化类的面板中触发操作,当按钮操作完成时更新另一个依赖项 (Holoviz)

    我正在使用 Parameterized Class 构建带有 Panel Holoviz 的仪表板 在本课程中 我想要一个按钮 当按下该按钮时开始训练模型 当模型完成训练时 它需要显示基于该模型的图表 如何使用类在面板中构建此类依赖关系 下
  • com.apple.InterfaceBuilder 错误-1。故事板无法打开

    我在一个项目中遇到了一些麻烦 需要一些帮助 我最近购买了一台 Mac Mini 并希望开始使用它来开发我的一些应用程序项目 所以我将文件从一台机器复制到另一台机器 两台计算机都运行 XCode 版本 4 6 3 复制的 5 个项目中 有 4
  • 如何在 M1 Mac 上捕获浮点异常?

    捕获浮点异常的方法取决于体系结构 这是我在 Intel x86 Mac 上成功测试的代码 它两次取负数的平方根 一次在之前 一次在之后 从而启用浮点异常捕获 第二次 fpe signal handler 叫做 include