How to enable SIGFPE signal when dividing by zero in IOS app?

I am developing an application in Xcode 4.5 (llvm 4.1 compiler) for ios 5/6 and use signal and exception handlers to report errors. However, I found that dividing by zero never causes a SIGFPE signal. On linux systems, I can use feenableexcept to set traps. But this is not defined in ios.

Setting the corresponding bits to fenv_t .__ fpscr does not work, at least for iphone 4 and 3gs.

+4
source share
2 answers

The feenableexcept function is a linux function that is not part of standard C or POSIX. You cannot transfer the SIGFPE method.

In fact, you need a different code to enable SIGFPE on the iOS simulator and on iOS devices, because the simulator runs x86 and the device launches ARM.

I think (but did not check) that you can enable SIGFPE by getting fenv_t using the fegetenv function, turning some bits on or off in fenv_t , and then passing it to fesetenv . The definition of fenv_t is processor dependent. Take a look at fenv.h

For ARM, fenv_t contains a field named __fpscr . It is a status and a floating point register . The bits that you allowed to switch are listed in fenv.h as __fpscr_trap_invalid , __fpscr_trap_divbyzero , etc. Presumably you want to enable the __fpscr_trap_divbyzero bit.

For x86, fenv_t contains two fields of interest: __control (control word x87) and __mxcsr (SSE register / status register).

The bits that you can switch to __control are determined by the constants FE_INEXACT , FE_UNDERFLOW , etc., defined in fenv.h I think you need to disable the bit to enable SIGFPE for these exceptions. Check processor manual, ยง8.1.5 .

The bits that you can switch to __mxcsr are determined by the constants _MM_MASK_INVALID , __MM_MASK_DENORM , etc. at xmmintrin.h . I think you need to disable the bit to enable SIGFPE . Check processor manual, ยง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 } 

You may also need to run #pragma STDC FENV_ACCESS ON for all processors.

Again, I did not check any of this. Good luck.

+3
source

Your options for solving this problem:

Do what Rob said, using one function to enable floating point division by zero capture, and then periodically check the flag:

 #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 

OR your other option is to enable the flag in xcode, which will throw an exception with all undefined rules by adding the following to the OTHER_CFLAGS build setup

 -fcatch-undefined-behavior 
0
source

Source: https://habr.com/ru/post/1438185/


All Articles