メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

計算例外の信号ハンドラーからの戻り値

プログラム エラーから信号ハンドラーが通常どおりに値を返す場合の未定義の動作

説明

この欠陥は、計算例外の信号 SIGFPESIGILL、または SIGSEGV をキャッチした後に信号ハンドラーが値を返した場合に発生します。

リスク

計算例外から通常どおり値を返す信号ハンドラーは未定義の動作です。信号をトリガーしたエラーの修正をハンドラーで試みる場合でも、プログラムは予期せぬ動作をする可能性があります。

修正方法

計算の前に変数の値の有効性をチェックして、信号ハンドラーを使用した例外のキャッチを回避します。ハンドラーによる計算例外の信号のキャッチを避けられない場合は、ハンドラー内で abort()quick_exit()、または _Exit() を呼び出してプログラムを停止します。

すべて展開する

#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>

static volatile sig_atomic_t denom;
/* Declare signal handler to catch division by zero 
computation error. */
void sig_handler(int s)
{
    int s0 = s;
    if (denom == 0)
    {
        denom = 1;
    }
	/* Normal return from computation exception
	signal */
    return; 
}


long func(int v)
{
    denom = (sig_atomic_t)v;
       
        if (signal(SIGFPE, sig_handler) == SIG_ERR)
        {
            /* Handle error */
        }
		
	long result = 100 / (long)denom;
    return result;
}
        
      

この例では、sig_handler がゼロ除算計算エラーを処理するように宣言されています。ハンドラーでは denom の値がゼロの場合は値を変更して返します。これは未定義の動作です。

修正 — abort() を呼び出してプログラムを停止

計算例外をキャッチした後、sig_handler から abort() を呼び出してプログラムを終了し、さらにエラーが発生しないようにします。

#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>

static volatile sig_atomic_t denom;
/* Declare signal handler to catch division by zero 
computation error. */

void sig_handler(int s)
{
    int s0 = s;
	/* call to abort() to exit the program */
    abort(); 
}

long func(int v)
{
    denom = (sig_atomic_t)v;
       
        if (signal(SIGFPE, sig_handler) == SIG_ERR)
        {
            /* Handle error */
        }
		
	long result = 100 / (long)denom;
    return result;
} 

結果情報

グループ: プログラミング
言語: C | C++
既定値: 手書きコードはオン、生成コードはオフ
コマンド ライン構文: SIG_HANDLER_COMP_EXCP_RETURN
影響度: Low

バージョン履歴

R2017b で導入