如何在IOS应用程序中启用零除SIGFPE信号?

如何在IOS应用程序中启用零除SIGFPE信号?,ios,xcode,exception-handling,divide-by-zero,Ios,Xcode,Exception Handling,Divide By Zero,我用Xcode 4.5(llvm 4.1编译器)为ios 5/6开发了一个应用程序,并使用信号和异常处理程序记录错误。然而,我发现除以零永远不会产生SIGFPE信号。在linux系统上,我可以使用feenableexcept设置陷阱。但这在ios中没有定义 将适当的位设置为fenv_t.u fpscr不起作用,至少对iPhone4和3gs是这样。feenableexcept函数是一个linux函数,不是标准C或POSIX的一部分。没有可移植的方法来启用SIGFPE 事实上,您需要不同的代码才能在

我用Xcode 4.5(llvm 4.1编译器)为ios 5/6开发了一个应用程序,并使用信号和异常处理程序记录错误。然而,我发现除以零永远不会产生SIGFPE信号。在linux系统上,我可以使用feenableexcept设置陷阱。但这在ios中没有定义


将适当的位设置为fenv_t.u fpscr不起作用,至少对iPhone4和3gs是这样。

feenableexcept函数是一个linux函数,不是标准C或POSIX的一部分。没有可移植的方法来启用
SIGFPE

事实上,您需要不同的代码才能在iOS模拟器和iOS设备上启用
SIGFPE
,因为模拟器运行x86,而设备运行ARM

我认为(但尚未测试)可以通过使用
fegetenv
函数获取
fenv_t
来启用
SIGFPE
,在
fenv_t
中打开或关闭一些位,然后将其传递给
fesetenv
函数。
fenv\u t
的定义是特定于处理器的。看看
fenv.h

对于ARM,
fenv\u t
包含一个名为
的字段。这是最新的。允许您切换的位在
fenv.h
中被枚举为
\uuu fpscr\u trap\u invalid
\uu fpscr\u trap\u divbyzero
等。您可能希望打开
\uu fpscr\u trap\u divbyzero

对于x86,
fenv\u t
包含两个感兴趣的字段:
\uu控制
(x87控制字)和
\uuu mxcsr
(SSE控制/状态寄存器)

您可以在
\u控制
中切换的位由
FE\u不精确
FE\u下溢
等在
fenv.h
中定义的常量定义。我认为您必须关闭位才能为这些异常启用
SIGFPE

可以在
\uuuuumxcsr
中切换的位由
xmmintrin.h
中的
MM\u MASK\u INVALID
MM\u MASK\u DENORM
等常量定义。我认为需要关闭位才能启用
SIGFPE
。检查处理器手册,§10.2.3

    fenv_t fe;
    if (fegetenv(&fe) != 0) {
        // error
    }

#if defined __arm__
    fe.__fpscr |= __fpscr_trap_divbyzero;
#elif defined __i386__
    fe.__control &= ~FE_DIVBYZERO;
    fe.__mxcsr &= ~_MM_MASK_DIV_ZERO;
#else
#error unknown processor architecture
#endif

    if (fesetenv(&fe) != 0) {
        // error
    }
您可能还需要对所有处理器进行
#pragma STDC FENV_访问


再说一次,我没有测试过这些。祝你好运。

解决此问题的方法有:

按照Rob的说法,使用一个函数启用浮点除零补漏白,然后定期检查标志:

#include "fenv.h"
#include <iostream>
#include <csignal>
void CheckForDivideByZeroException()
{
    int set_excepts;
    set_excepts = fetestexcept(FE_DIVBYZERO);

    if (set_excepts & FE_DIVBYZERO) {
        cerr<<"Divide by zero!!!"<<endl;
        feclearexcept(FE_DIVBYZERO);
    }
}
void EnableDivideByZeroExceptions()
{
    fenv_t fe;
    if (fegetenv(&fe) != 0) {
        cerr<<"ERROR - Unable to get floating point status and control register"<<endl;
        raise(SIGINT);
    }

#if defined __arm__
    fe.__fpscr |= __fpscr_trap_divbyzero;
#elif defined __i386__
    fe.__control &= ~FE_DIVBYZERO;
    fe.__mxcsr &= ~_MM_MASK_DIV_ZERO;
#else
#error unknown processor architecture
#endif

    if (fesetenv(&fe) != 0) {
        cout<<"ERROR - Unable to trap div by zero errors"<<endl;
        raise(SIGINT);
    }
}
#endif

这不起作用,即使fesetenv将值设置为ok。顺便说一下,这个i386魔术也不起作用。这只会让cpu设置标志,不会引发异常。如果按照Rob所述启用标志,则需要在每次运行循环或执行除法后检查标志。类似于:int set_excepts=fetestexcept(FE_DIVBYZERO);if(set_excepts&FE_DIVBYZERO){cerrth这听起来是一个正确的方法,适用于桌面和模拟器,但我无法使它适用于设备-既不适用于
\uu arm\uuuuuu
,也不适用于
\uuu arm64\uuuuuu
。我已经对它进行了一条指令一条指令的调试,并达到了fesetenv()执行FMXR指令,将更新的值写入FPSCR,但寄存器的值不变。苹果公司的ARM体系结构实现似乎不支持浮点捕获。根据ARM有限公司的参考手册,这是实现该体系结构时允许的选项。
-fcatch-undefined-behavior