3.2.7 例外を一時的に無効化する関数

feholdexcept および feupdateenv 関数では、例外トラップを一時的に無効にすることができます。

ARM® コンパイラ ツールチェーンでは、AArch64 ターゲット用の浮動小数点の例外のトラップはサポートされません。

これらの機能では、例外をサポートする浮動小数点モデルが必要です。 ARM コンパイラ コンパイラ 6 では、これはデフォルトで有効になっています。-ffast-math などの armclang コマンドラインオプションによって無効になります。
これらの関数を使用すると、例外が発生しそうなコードを実行するときに、例外のトラップを回避することができます。これらの関数は、トラップされた例外で ARM のデフォルトの動作を使用する場合などに便利です。デフォルトでは、SIGFPE が生成され、アプリケーションが終了します。
int feholdexcept(fenv_t *envp);
void feupdateenv( const fenv_t *envp);
feholdexcept() 関数は、指定された fenv_t 変数に現在の浮動小数点環境を保存し、すべての例外のトラップを無効に設定し、すべての例外のスティッキーフラグをクリアします。ユーザは次に、不都合な例外が発生しそうなコードを実行し、それらの例外のスティッキーフラグがクリアされていることを確認できます。次に feupdateenv() を呼び出します。これによって例外トラップが復元され、必要に応じて呼び出されます。例えば、frob() 関数によって、アンダーフロー例外または無効演算例外が発生する可能性があるとします(いずれの例外もトラップされると仮定します)。アンダーフロー例外は無視し、無効演算が試行されたかどうかだけを確認するには、以下のコードを実装します。
fenv_t env; feholdexcept(&env); frob(); feclearexcept(FE_UNDERFLOW); feupdateenv(&env);
これにより、frob() 関数によってアンダーフローが発生しても、そのアンダーフローは feclearexcept() によって再びクリアされるため、feupdateenv() が呼び出されてもトラップは発生しません。ただし、frob() によって無効演算例外が発生した場合には、feupdateenv() が呼び出されたときにスティッキーフラグが設定されるため、トラップハンドラが呼び出されます。
このメカニズムが C99 で提供されている理由は、C99 では個々の例外について例外トラップを変更する方法が指定されていないためです。より効果的な方法に、無効演算トラップを有効にしたまま、__ieee_status() を使用してアンダーフロートラップを無効にする方法があります。この方法には、無効演算トラップハンドラに、無効演算に関するすべての情報(どの演算が、どのデータに対して実行されたかという情報)が渡されるため、その演算の結果を生成できるという利点があります。C99 の方法では、無効演算トラップハンドラは事後に呼び出され、例外の原因に関する情報も渡されず、代用できる結果を返すには呼び出されるのが遅すぎるなどの欠点があります。
関連する参考文書
3.2.2 ARM 浮動小数点環境を制御するための C99 互換関数
5.5 __ieee_status()
非機密扱いPDF file icon PDF 版ARM DUI0808CJ
Copyright © 2014, 2015 ARM.All rights reserved.