我在 Xcode 4.5(llvm 4.1 编译器)中为 ios 5/6 开发了一个应用程序,并使用信号和异常处理程序来记录错误。但是我发现除以零永远不会引发 SIGFPE 信号。在 linux 系统上,我可以使用 feenableexcept 来设置陷阱。但这在ios中没有定义。
将适当的位设置为 fenv_t.__fpscr 不起作用,至少对于 iphone 4 和 3gs 而言。
我在 Xcode 4.5(llvm 4.1 编译器)中为 ios 5/6 开发了一个应用程序,并使用信号和异常处理程序来记录错误。但是我发现除以零永远不会引发 SIGFPE 信号。在 linux 系统上,我可以使用 feenableexcept 来设置陷阱。但这在ios中没有定义。
将适当的位设置为 fenv_t.__fpscr 不起作用,至少对于 iphone 4 和 3gs 而言。
该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_INEXACT
、FE_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
为所有处理器执行此操作。
同样,我还没有测试过这些。祝你好运。
您解决此问题的选择是:
按照 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