我为ios 5/6在Xcode 4.5(llvm 4.1编译器)中开发了一个应用程序,并使用信号和异常处理程序来记录错误。但是我发现除零从不会提高SIGFPE信号。在linux系统上,我可以使用feenableexcept来设置陷阱。但这并没有在ios中定义。
将适当的位设置为fenv_t .__ fpscr不起作用,至少对于iphone 4和3gs而言。
答案 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_UNDERFLOW
,fenv.h
等常量定义。我认为您必须关闭关闭位以启用SIGFPE
这些例外。 Check the processor manual, §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
。
同样,我还没有测试过这些。祝你好运。
答案 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