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

时间:2012-10-06 18:06:32

标签: ios xcode exception-handling divide-by-zero

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

将适当的位设置为fenv_t .__ fpscr不起作用,至少对于iphone 4和3gs而言。

2 个答案:

答案 0 :(得分:3)

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

实际上,您需要使用不同的代码在iOS模拟器和iOS设备上启用SIGFPE,因为模拟器运行x86并且设备运行ARM。

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

对于ARM,fenv_t包含名为__fpscr的字段。这是floating point status and control register。允许切换的位在fenv.h中枚举为__fpscr_trap_invalid__fpscr_trap_divbyzero等。大概您要打开__fpscr_trap_divbyzero位。

对于x86,fenv_t包含两个感兴趣的字段:__control(x87控制字)和__mxcsr(SSE控制/状态寄存器)。

您可以在__control中切换的位由FE_INEXACT中定义的FE_UNDERFLOWfenv.h等常量定义。我认为您必须关闭关闭位以启用SIGFPE这些例外。 Check the processor manual, §8.1.5

您可以在__mxcsr中切换的位由_MM_MASK_INVALID中的__MM_MASK_DENORMxmmintrin.h等常量定义。我认为您需要将关闭位以启用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_ACCESS ON

同样,我还没有测试过这些。祝你好运。

答案 1 :(得分:0)

解决此问题的方法是:

通过使用一个函数使浮点除以零陷阱,然后定期检查标志来执行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

或者您的另一个选择是通过在OTHER_CFLAGS构建设置中添加以下内容来启用xcode中的标志,该标志将引发具有所有未定义行为的异常

-fcatch-undefined-behavior