メインコンテンツ

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

CERT C++: ERR58-CPP

main() が実行を開始する前にスローされるすべての例外を処理する

説明

ルール定義

main() が実行を開始する前にスローされるすべての例外を処理します。1

Polyspace 実装

ルール チェッカーは、"プログラム起動中に発生する例外" をチェックします。

すべて展開する

問題

この問題は、main() が実行を開始する前、グローバル変数と静的変数の構築中に例外が発生する可能性がある場合に発生します。例外が起動フェーズ中に発生する場合、発生した例外をコンパイラが処理するために実行できる例外ハンドラーを記述できません。この例外は未処理例外になります。たとえば、例外を処理するため、main()function-try-catch ブロックとして実装できます。起動フェーズ中に発生した例外を処理できる catch ブロックはなく、発生したこれらの例外は未処理例外になります。

グローバル変数または静的変数の初期化または宣言をするために呼び出し可能なエンティティを呼び出すとき、これらのエンティティはプログラム起動中に実行されます。Polyspace® はこれらのエンティティがプログラム起動中に例外を発生する可能性があるかどうかを、特定の仮定によりチェックします。

  • 関数:初期化子関数またはコンストラクターを直接呼び出してグローバル変数または静的変数を初期化するとき、Polyspace はその関数で例外が発生するかどうかをチェックして、関数で例外が発生する可能性がある場合は変数宣言にフラグを設定します。Polyspace は関数の例外指定にかかわらず、その関数で例外が発生する可能性があるかどうかを推定します。たとえば、noexcept コンストラクターによって例外が発生する場合、Polyspace はフラグを設定します。初期化子またはコンストラクターが別の関数を呼び出すと、Polyspace は、呼び出された関数が noexcept(<false>) として指定されている場合にのみ、例外を発生させる可能性があると仮定します。std::string のコンストラクターなど、一部の標準ライブラリ関数ではメモリ割り当てを実行するため関数へのポインターを使用し、これが例外を発生させる可能性があります。Polyspace はこれらの関数が使用されるとき変数宣言にはフラグを設定しません。

  • 外部関数:外部関数を呼び出してグローバル変数または静的変数を初期化するとき、外部関数が noexcept(<false>) として指定されている場合、Polyspace は宣言にフラグを設定します。

  • バーチャル関数:バーチャル関数を呼び出してグローバル変数または静的変数を初期化するとき、そのバーチャル関数がいずれかの派生クラスで noexcept(<false>) として指定されている場合、Polyspace はフラグを設定します。たとえば、基底クラスで noexcept(<true>) として宣言され、派生クラスでは noexcept(<false>) として宣言されたバーチャル初期化子関数を使用する場合、Polyspace はフラグを設定します。

  • 関数へのポインター:関数へのポインターを使用してグローバル変数または静的変数を初期化するとき、Polyspace は、関数へのポインターは例外を発生させないものと仮定します。

Polyspace は以下を無視します。

  • デストラクターで発生する例外

  • atexit() 操作で発生する例外

Polyspace は、例外のチェックの際に動的なコンテキストも無視します。たとえば、特定の動的コンテキストのみで例外を発生させる関数を使用してグローバル変数または静的変数を初期化するとします。Polyspace はそのような宣言に、その例外が決して発生しないとしてもフラグを設定します。このような違反は、Polyspace でコメントを使用して正当化できます。

リスク

例外が処理されないと、使用しているハードウェアとソフトウェアの組み合わせによっては、コンパイラはスタックをアンワインドせずにコードの実行を異常終了する可能性があります。静的オブジェクト obj の構築で例外が発生する可能性がある次のコードを検討します。

class A{
	A(){throw(0);}	
};

static A obj;

main(){
	//...
}
main() が開始する前に、静的オブジェクト objA() を呼び出すことにより構築されます。A() によって例外が発生する場合、ハンドラーをその発生した例外と一致させることはできません。使用しているハードウェアとソフトウェアの組み合わせに基づいて、このような例外はスタックをアンワインドせずにプログラムを終了させる可能性があり、メモリ リークとセキュリティの脆弱性につながります。

修正方法

プログラムの起動前または終了後に実行される可能性があるコードの一部で、例外を発生させる操作を避けます。たとえば、静的オブジェクトおよびグローバル オブジェクトのコンストラクターおよびデストラクターで例外を発生させる可能性がある操作を避けます。

グローバル ポインター arr の構築で動的メモリ割り当てを必要とする次のコードを検討します。

#include <stdexcept>
void* alloc(size_t s) noexcept {          
	return new int[s];
}
int* arr = (int*)alloc(5);//Noncompliant
int main(){
	//..
	return 0;
}

new 演算子を使用した動的メモリ割り当ては例外を発生させる可能性があります。arr の構築は、main() が実行を開始する前に例外を発生させる可能性があるので、Polyspace は宣言にフラグを設定します。

修正

グローバル オブジェクトの構築の際、例外を発生させる可能性がある操作を避けます。たとえば、グローバル ポインター arrnullptr を使用して初期化できます。その後、main() 内の try-catch コード ブロック内で arr のメモリを割り当てます。

#include <stdexcept>
#include<vector>
void* alloc(size_t s) noexcept {          
	return new int[s];
}
int* arr =nullptr;
int main(){
	try{
		arr =  (int*)alloc(5);	
	}
	catch(std::bad_alloc e){
		//..
	}
	//..
	return 0;
}

この場合、動的メモリ割り当て操作は main()std::bad_alloc 例外を発生させますが、これはコードの catch ブロックで処理できます。

チェック情報

グループ: 08.例外とエラーの取り扱い (ERR)

バージョン履歴

R2020b で導入

すべて展開する


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.