メインコンテンツ

AUTOSAR C++14 Rule A3-3-2

Static and thread-local objects shall be constant-initialized

説明

ルール定義

静的オブジェクトとスレッド ローカル オブジェクトは定数初期化するものとします。

根拠

静的オブジェクトとスレッド ローカル オブジェクトは、コード実行の開始時点で初期化されます。C++ 言語標準では、複数の静的オブジェクトまたはスレッド ローカル オブジェクトの初期化順序が部分的にしか定義されず、ビルドごとに順序が変化する可能性があります。静的オブジェクトまたはスレッド ローカル オブジェクトを別のそのようなオブジェクトから初期化する場合は、オブジェクトが初期化される前に、コンパイラが後者のオブジェクトにアクセスする可能性があります。初期化前のアクセスを回避するには、コンパイル時に定数に評価されるオブジェクトを使用して、静的オブジェクトとスレッド ローカル オブジェクトを初期化します。定数を使用した初期化は、変数を使用した初期化の前に行われ、多くはコンパイル時に行われます。

このルールは、グローバル変数、静的変数、静的クラス メンバー変数、および静的関数スコープ変数に適用されます。

Polyspace 実装

Polyspace® は、コンパイル時に定数に評価されない初期化子とコンストラクターを使用した静的オブジェクトまたはスレッド ローカル オブジェクトの初期化にフラグを設定します。静的オブジェクトまたはスレッド ローカル オブジェクトを定数初期化するには、以下を使用します。

  • 定数引数のみを使用する constexpr コンストラクター

  • 定数式

文字列オブジェクトでは不明なサイズの動的メモリ割り当てが使用されるため、コンパイラはそれらをコンパイル時に評価できません。Polyspace は、初期化子が指定されているかどうかに関係なく、文字列オブジェクトの初期化にフラグを設定します。

クラスのコンストラクターが constexpr ではない場合、そのクラスのグローバル、静的、またはスレッド ローカル インスタンスを定数初期化できないため、違反が発生します。たとえば、このコードではクラス myClassconstexpr コンストラクターがありません。このクラスのグローバル、static、またはスレッド ローカル インスタンスは違反となります。

class myClass
{
  public:
    myClass() {}  //no a constexpr
};

namespace
{
  myClass myObject{};  //Noncompliant  
} // namespace

void foo()
{
  static myClass myStaticObject{};      // Noncompliant
}

トラブルシューティング

ルール違反が想定されるものの、Polyspace から報告されない場合は、コーディング規約違反が想定どおりに表示されない理由の診断を参照してください。

すべて展開する

#include <cstdint>
#include <limits>
#include <string>
class A{
	//..
public:
	constexpr A(){
		//...
	}
};
class B{
	//..
public:
	B(){
		//...
	}
};
const int global_const_a = 10;              // Compliant
const int global_const_b = global_const_a;  // Compliant 
int global_a = 10;                          // Compliant  
int global_b = global_a;                    // Noncompliant 
static std::string global_name = "Name";    // Noncompliant
static std::string global_id;               // Noncompliant 
char *ptr = "hello world";                  // Compliant
char arr_up[3] = {'U','p','\0'};            // Compliant  
char container[10];                         // Compliant
extern const int global_extern_c;
const int global_const_c = global_extern_c; // Noncompliant 
static A obj1{};							//Compliant
static B obj2{}; 							//Noncompliant
main()
{
	
	//
}  

Polyspace は、以下の初期化にフラグを設定します。

  • global_a による global_b の初期化。これは、global_b がコンパイル時に定数に評価されるかどうかはこれらの変数が初期化される順序に依存するためです。

  • global_nameglobal_id の初期化。これは、コンパイラがコンパイル時に文字列オブジェクトのコンストラクターを評価できないためです。

  • extern 変数 global extern_c による global_const_c の初期化。これは、コンパイラがコンパイル時に extern 変数を評価できないためです。

  • コンストラクター B::B() を呼び出す obj2。これは、コンストラクターが constexpr として指定されていないためです。

Polyspace は、以下の初期化にフラグを設定しません。

  • global_const_a による global_const_b の初期化。これは、コンパイラが初期化順序に関係なくコンパイル時にこれらのオブジェクトを評価できるためです。

  • リテラルによる global_const_aglobal_a の初期化。これは、コンパイラがコンパイル時にリテラルを評価できるためです。

  • リテラル初期化子によるグローバル文字ポインターと配列の初期化。これは、コンパイラがコンパイル時に静的メモリを割り当てることができるためです。

  • コンストラクター A::A() を呼び出す obj1。これは、コンストラクターが constexpr として指定されているためです。

チェック情報

グループ: 基本概念
カテゴリ: Required、Automated

バージョン履歴

R2020a で導入