4

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

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

4

2 回答 2

5

feenableexcept函数是一个不属于标准 C 或 POSIX 的 linux 函数。没有可移植的方式来启用SIGFPE.

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

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

对于 ARM,fenv_t包含一个名为__fpscr. 这是浮点状态和控制寄存器。您可以切换的位被列举fenv.h__fpscr_trap_invalid__fpscr_trap_divbyzero等。大概您想要打开该__fpscr_trap_divbyzero位。

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

您可以切换的位__control由 中定义的FE_INEXACTFE_UNDERFLOW等常量定义fenv.h。我认为您必须关闭这些位才能启用SIGFPE这些异常。 检查处理器手册,§8.1.5

可以切换的位__mxcsr由 中的_MM_MASK_INVALID__MM_MASK_DENORM等常量定义xmmintrin.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为所有处理器执行此操作。

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

于 2012-10-06T19:15:28.703 回答
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
于 2013-03-08T20:21:22.680 回答