2012-10-06 50 views
4

我在Xcode 4.5(llvm 4.1編譯器)中爲ios 5/6開發應用程序,並使用信號和異常處理程序記錄錯誤。但是我發現,零除不會引發SIGFPE信號。在Linux系統上,我可以使用feenableexcept來設置陷阱。但是這並沒有在ios中定義。如何在iOS應用程序中啓用除零的SIGFPE信號?

將適當的位設置爲fenv_t .__ fpscr不起作用,至少對於iphone 4和3gs而言。

回答

3

feenableexcept函數是一個linux函數,它不是標準C或POSIX的一部分。沒有便攜式的方式來啓用SIGFPE

實際上,您需要不同的代碼才能在iOS模擬器和iOS設備上啓用SIGFPE,因爲模擬器運行x86並且設備運行ARM。

我認爲(但沒有測試),您可以通過使用fegetenv功能得到一個fenv_t,在fenv_t打開或關閉某些位,然後將它傳遞給fesetenv功能使能SIGFPEfenv_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_INEXACTFE_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

同樣,我還沒有測試過任何這個。祝你好運。

+0

這沒有按」儘管fesetenv確定了值,順便說一句,這個i386魔法也不起作用。 – Tertium

+0

這隻會啓用cpu來設置標誌,它不會引發異常。如果您按照Rob的描述啓用該標誌,則需要檢查每個運行循環的標誌或執行除法後的標誌。像這樣: int set_excepts = fetestexcept(FE_DIVBYZERO); if(set_excepts&FE_DIVBYZERO)cerr <<「除以零!!!」<< endl; feclearexcept(FE_DIVBYZERO); } – Snickers

+0

這聽起來像一個正確的方法,並且適用於桌面和模擬器,但是我無法使它在設備上工作 - 既不是'__arm__',也不是'__arm64__'。我已經通過指令對指令進行了調試,並且達到了fesetenv()執行FMXR指令將更新值寫入FPSCR的地步,但寄存器的值不會改變。 – kjam

0

您的選項來解決這個問題是:

做什麼羅布說,通過使用一個功能,使零陷浮點除法,然後定期檢查標誌:

#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 

或您另一種選擇是,以使在Xcode的標誌將被添加以下到您的OTHER_CFLAGS引發異常所有未定義行爲構建設置

-fcatch-undefined-behavior 
相關問題