MISRA C++:2008 Rule 15-3-1
Exceptions shall be raised only after startup and before termination of the program
説明
ルール定義
Exceptions shall be raised only after startup and before termination of the program. 1
根拠
C++ では、例外処理のプロセスが main() の実行中に発生します。ここでは、複数の異なるスコープで発生した例外が同じまたは隣接するスコープ内の例外ハンドラーによって処理されます。main() の実行の開始前は、コンパイラは起動フェーズにあり、main() の実行の終了後に、終了フェーズに移行します。この 2 つのフェーズ中に、コンパイラは、一連の事前に定義された操作を実行しますが、コードは実行しません。
起動フェーズと終了フェーズのどちらかで例外が発生する場合は、そのようなフェーズでコンパイラにより実行可能な例外ハンドラーを記述することはできません。たとえば、例外を処理するため、main() を function-try-catch ブロックとして実装できます。main() 内の catch ブロックは、main() で発生した例外しか処理できません。起動または終了フェーズ中に発生した例外を処理できる catch ブロックは存在しません。このような例外が発生した場合は、コンパイラがスタックをアンワインドせずにコードの実行を異常終了する可能性があります。静的オブジェクト obj の構築と破棄で例外が発生する可能性がある次のコードについて考えます。
class A{
A(){throw(0);}
~A(){throw(0)}
};
static A obj;
main(){
//...
}obj は、main() の開始前に A() を呼び出すことによって構築され、main() の終了後に ~A() を呼び出すことによって破棄されます。A() または ~A() で例外が発生した場合は、それに対応可能な例外ハンドラーが存在しません。実装に基づいて、このような例外はスタックをアンワインドせずにプログラムを終了させる可能性があり、メモリ リークやセキュリティの脆弱性につながります。プログラムの起動前または終了後に実行される可能性があるコードの一部で、例外を発生させる操作を避けます。たとえば、静的オブジェクトおよびグローバル オブジェクトのコンストラクターおよびデストラクターで例外を発生させる可能性がある操作を避けます。
Polyspace 実装
Polyspace® は、例外を発生させる可能性のある呼び出し可能エンティティを使用するグローバルまたは静的変数宣言にフラグを設定します。次に例を示します。
関数: 初期化子関数またはコンストラクターを直接呼び出してグローバル変数または静的変数を初期化するとき、Polyspace はその関数で例外が発生するかどうかをチェックして、関数で例外が発生する可能性がある場合は変数宣言にフラグを設定します。Polyspace は関数の例外指定にかかわらず、その関数で例外が発生する可能性があるかどうかを推定します。たとえば、
noexceptコンストラクターによって例外が発生する場合、Polyspace はフラグを設定します。初期化子またはコンストラクターが別の関数を呼び出すと、Polyspace は、呼び出された関数がnoexcept(<false>)として指定されている場合にのみ、例外を発生させる可能性があると仮定します。std::stringのコンストラクターなど、一部の標準ライブラリ関数では、メモリ割り当てを実行するために関数へのポインターが使用され、これが例外を発生させる可能性があります。Polyspace はこれらの関数が使用されるときの変数宣言にはフラグを設定しません。外部関数:外部関数を呼び出してグローバル変数または静的変数を初期化するとき、外部関数が
noexcept(<false>)として指定されている場合、Polyspace は宣言にフラグを設定します。バーチャル関数:バーチャル関数を呼び出してグローバル変数または静的変数を初期化するとき、そのバーチャル関数がいずれかの派生クラスで
noexcept(<false>)として指定されている場合、Polyspace はフラグを設定します。たとえば、基底クラスでnoexcept(<true>)として宣言され、派生クラスではnoexcept(<false>)として宣言されたバーチャル初期化子関数を使用する場合、Polyspace はフラグを設定します。関数へのポインター:関数へのポインターを使用してグローバル変数または静的変数を初期化する場合、Polyspace は、関数へのポインターで例外が発生しないものと仮定します。
Polyspace は以下を無視します。
デストラクターで発生する例外
atext()操作で発生する例外
Polyspace は、例外のチェックの際に動的なコンテキストも無視します。たとえば、特定の動的コンテキストでのみ例外を発生させる関数を使用してグローバル変数または静的変数を初期化するとします。Polyspace は、例外が決して発生しない場合でもそのような宣言にフラグを設定します。このような違反は、Polyspace でコメントを使用して正当化できます。
トラブルシューティング
ルール違反が想定されるものの、Polyspace から報告されない場合は、コーディング規約違反が想定どおりに表示されない理由の診断を参照してください。
例
チェック情報
| グループ: Exception handling |
| カテゴリ: 必要 |
バージョン履歴
R2020b で導入
1 All MISRA coding rules and directives are © Copyright The MISRA Consortium Limited 2021.
The MISRA coding standards referenced in the Polyspace Bug Finder™ documentation are from the following MISRA standards:
MISRA C:2004
MISRA C:2012
MISRA C:2023
MISRA C++:2008
MISRA C++:2023
MISRA and MISRA C are registered trademarks of The MISRA Consortium Limited 2021.