我在Xcode 4.5(llvm 4.1編譯器)中爲ios 5/6開發應用程序,並使用信號和異常處理程序記錄錯誤。但是我發現,零除不會引發SIGFPE信號。在Linux系統上,我可以使用feenableexcept來設置陷阱。但是這並沒有在ios中定義。如何在iOS應用程序中啓用除零的SIGFPE信號?
將適當的位設置爲fenv_t .__ fpscr不起作用,至少對於iphone 4和3gs而言。
我在Xcode 4.5(llvm 4.1編譯器)中爲ios 5/6開發應用程序,並使用信號和異常處理程序記錄錯誤。但是我發現,零除不會引發SIGFPE信號。在Linux系統上,我可以使用feenableexcept來設置陷阱。但是這並沒有在ios中定義。如何在iOS應用程序中啓用除零的SIGFPE信號?
將適當的位設置爲fenv_t .__ fpscr不起作用,至少對於iphone 4和3gs而言。
feenableexcept
函數是一個linux函數,它不是標準C或POSIX的一部分。沒有便攜式的方式來啓用SIGFPE
。
實際上,您需要不同的代碼才能在iOS模擬器和iOS設備上啓用SIGFPE
,因爲模擬器運行x86並且設備運行ARM。
我認爲(但沒有測試),您可以通過使用fegetenv
功能得到一個fenv_t
,在fenv_t
打開或關閉某些位,然後將它傳遞給fesetenv
功能使能SIGFPE
。 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
。
同樣,我還沒有測試過任何這個。祝你好運。
您的選項來解決這個問題是:
做什麼羅布說,通過使用一個功能,使零陷浮點除法,然後定期檢查標誌:
#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
這沒有按」儘管fesetenv確定了值,順便說一句,這個i386魔法也不起作用。 – Tertium
這隻會啓用cpu來設置標誌,它不會引發異常。如果您按照Rob的描述啓用該標誌,則需要檢查每個運行循環的標誌或執行除法後的標誌。像這樣: int set_excepts = fetestexcept(FE_DIVBYZERO); if(set_excepts&FE_DIVBYZERO)cerr <<「除以零!!!」<< endl; feclearexcept(FE_DIVBYZERO); } – Snickers
這聽起來像一個正確的方法,並且適用於桌面和模擬器,但是我無法使它在設備上工作 - 既不是'__arm__',也不是'__arm64__'。我已經通過指令對指令進行了調試,並且達到了fesetenv()執行FMXR指令將更新值寫入FPSCR的地步,但寄存器的值不會改變。 – kjam