4

特定の状況で停止するために、故意にゼロ除算を実行する (そして結果を揮発性変数に格納する) プログラムがあります。ただし、ゼロ除算を実行するマクロを変更せずに、この停止を無効にできるようにしたいと考えています。

無視する方法はありますか?

使ってみました

#include <signal.h>
...
int main(void) {
  signal(SIGFPE, SIG_IGN);
  ...
}

ただし、「浮動小数点例外(コアダンプ)」というメッセージで停止します。

実際には値を使用しないので、変数に何が割り当てられているかはあまり気にしません。0、ランダム、未定義...

編集:これが最も移植性が高いわけではないことはわかっていますが、多くの異なる OS で実行される組み込みデバイスを対象としています。デフォルトの停止アクションはゼロ除算です。他のプラットフォームでは、ウォッチドッグによる再起動を強制するために別のトリックが必要です (割り込みを無効にした無限ループなど)。PC (Linux) のテスト環境で、assert などに頼らずに、0 除算での停止を無効にしたかったのです。

4

8 に答える 8

6

さて、最初に、非推奨のの代わりにsigaction(2)signal()を使用する必要があります。

第二に、プログラムを終了する目的でSIGFPEを使用することは、明らかにばかげています。副作用のために他のシグナルを仮帆装する代わりに、SIGTERMやSIGUSR1のようなシグナルを発生させ、そのセマンティック値を無視する必要があるからです。より具体的には、sigaction(2)のマニュアルページには、SIGFPEに関する宣伝文句のあるNOTESセクションがあり、意図した使用法が破られている1つまたは2つの方法を示しています。

あなたがすべきことは、あなたが終了したいときにシグナルをraise(3)することです。次に、構造体のsa_handlerフィールドを使用して、その信号のsigaction無視(SIG_IGN)または終了(SIG_DFL)を変更します。

int main(void){
  struct sigaction my_action;

  my_action.sa_handler = SIG_IGN;
  my_action.sa_flags = SA_RESTART;
  sigaction(SIGUSR1、&my_action、NULL);

  raise(SIGUSR1); /*無視されます*/

  my_action.sa_handler = SIG_DFL;
  sigaction(SIGUSR1、&my_action、NULL);

  raise(SIGUSR1); /*終了します*/

  0を返します。
}

とはいえ、単純なの代わりにシグナルを使用する理由がわかりませんexit()

于 2009-01-07T09:00:07.243 に答える
4

停止するために意図的にゼロ除算を実行するのはなぜですか? あなたexit(-1)または同等のことができませんでしたか?

特に、0 による除算の結果が必要ない場合、これは意味がありません。

于 2009-01-07T08:09:53.993 に答える
2

の戻り値を確認してください

signal(SIGFPE, SIG_IGN);

を取得した場合SIG_ERRは、の値を確認errnoして、何が問題だったかを確認してください。それはあなたが移植できる限りのことです。

ゼロ除算を変更したくないことは知っていますが、移植性がなく、直感に反します。何らかの条件が発生した場合にコアダンプしたいのですが、コードを編集せずにこの動作を無効にできますか?とを使用assertNDEBUGます。

于 2009-01-07T09:06:30.070 に答える
1

これは移植できませんが、x86 では FPU を制御することで移植できます。

Linuxでgccを使用する(他のコンパイラにも同様の機能があると確信しています):

#include <fpu_control.h>

_FPU_SETCW (_FPU_DEFAULT);

_FPU_DEFAULT のデフォルトは _FPU_MASK_ZM に設定されているため (ZM は Zero-Divide-Mask を表します)。

于 2009-01-07T08:22:49.427 に答える
1
void handler(int trapId)
{
   // Whatever
}

signal(SIGFPE, handler);
于 2012-05-22T12:39:57.053 に答える
0

あまり工夫されていない式でプログラムを終了させることができますか? 例えば:

#include <signal.h>

#ifdef DEBUG
#define DIE_HERE raise(SIGFPE)
#else
#define DIE_HERE
#endif

プログラムの他の部分が意図せずにゼロで除算されないように、デフォルトの動作をオーバーライドすることをためらっています。または、コア ダンプを取得するために強制的にこの方法で終了させる場合は、デバッガー内でブレークポイントを使用することを検討してください。または、gdb デバッガーを使用しているシステムを使用している場合は、gcore ユーティリティが役立つ場合があります。

于 2009-01-07T08:30:02.813 に答える
0

クラッシュするコードを確認したら、コードを変更して別の方法で停止することもお勧めします。そうでない場合は、インストールを試みることができます

于 2012-02-16T09:54:19.963 に答える
0

クラッシュするコードを制御できる場合は、コードを変更して別の方法で停止することもお勧めします。そうでない場合は、代わりに空のシグナル ハンドラーをインストールすることもできます (つまり、) を使用しますsignal(SIGFPE, &EmptyFunction) が、まだ未定義の動作に依存しているため、他のシステム、または他のカーネルまたは C ライブラリで引き続き動作するという保証はありません。バージョン。

于 2009-01-07T09:55:14.577 に答える