メインコンテンツ

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

終了ハンドラーが異常終了しました

プログラムの正常な実行に割り込む終了ハンドラー関数

説明

この欠陥は、プログラムで想定されている終了順序に割り込む関数が終了ハンドラー自体によって呼び出され、異常終了が引き起こされた場合に発生します。

  • 終了ハンドラーは、プログラムが終了したときに実行するように指定された関数です。この関数は、atexit、(WinAPI) _onexitat_quick_exit() などの特定の関数で最初に登録されます。

  • 異常終了の原因となる可能性がある関数には、exitabortlongjmp、(WinAPI) _onexit などがあります。

リスク

終了ハンドラーによってプログラムが終了される場合、未定義の動作になる可能性があります。プログラムの異常終了は、他の終了ハンドラーが呼び出されていないことを意味します。このような追加の終了ハンドラーでは、追加のクリーン アップやその他の必要な終了手順が行われる可能性があります。

修正方法

終了ハンドラーが正常終了するのを妨げる関数呼び出しを終了ハンドラー内から削除します。

すべて展開する

#include <stdlib.h>

volatile int some_condition = 1;
void demo_exit1(void)
{
    /* ... Cleanup code ... */
    return;
}
void exitabnormalhandler(void)
{
    if (some_condition)
    {
        /* Clean up */
        exit(0);
    }
    return;
}

int demo_install_exitabnormalhandler(void)
{

    if (atexit(demo_exit1) != 0) /* demo_exit1() performs additional cleanup */
    {
        /* Handle error */
    }
    if (atexit(exitabnormalhandler) != 0)
    {
        /* Handle error */
    }
    /* ... Program code ... */
    return 0;
}

この例では、demo_install_exitabnormalhandler が 2 つの終了ハンドラー demo_exit1exitabnormalhandler を登録しています。終了ハンドラーは、登録時とは逆順に呼び出します。プログラムの終了時、exitabnormalhandler が実行され、次に demo_exit1 が実行されます。しかし、exitabnormalhandler が、プログラムの終了プロセスに割り込む exit を呼び出しています。終了ハンドラー内にこの exit があると、プログラムが安全にクリーン アップされずに終了するため、未定義の動作が発生します。

修正 — 終了ハンドラーから exit を削除

考えられる 1 つの修正方法として、終了ハンドラーが正常終了するようにします。この例では、exitexitabnormalhandler から削除し、終了プロセスが想定どおりに完了できるようにします。

#include <stdlib.h>

volatile int some_condition = 1;
void demo_exit1(void)
{
    /* ... Cleanup code ... */
    return;
}
void exitabnormalhandler(void)
{
    if (some_condition)
    {
        /* Clean up */
        /* Return normally */
    }
    return;
}

int demo_install_exitabnormalhandler(void)
{

    if (atexit(demo_exit1) != 0) /* demo_exit1() continues clean up */
    {
        /* Handle error */
    }
    if (atexit(exitabnormalhandler) != 0) 
    {
        /* Handle error */
    }
    /* ... Program code ... */
    return 0;
}

結果情報

グループ: プログラミング
言語: C | C++
既定値: オフ
コマンド ライン構文: EXIT_ABNORMAL_HANDLER
影響度: Medium

バージョン履歴

R2016b で導入