Main Content

AUTOSAR C++14 Rule A3-3-2

Static and thread-local objects shall be constant-initialized

Since R2020a

Description

Rule Definition

Static and thread-local objects shall be constant-initialized.

Rationale

Static and thread-local objects are initialized at the start of code execution. The C++ language standard only partially defines the initialization order of multiple static or thread-local objects and the order can change from build to build. If you initialize a static or thread-local object from another such object, the compiler might access the latter object before it is initialized. To avoid access before initialization, initialize static and thread-local objects by using objects that evaluate to a constant at compile time. Initialization with constants occurs before initialization with variables and often happens at compile time.

This rule applies to global variables, static variables, static class member variables, and static function-scope variables.

Polyspace Implementation

Polyspace® flags initializations of static or thread-local objects using initializers and constructors that do not evaluate to constants at compile time. To constant-initialize static or thread-local objects, use:

  • A constexpr constructor with only constant arguments

  • A constant expression

  • A value

Because string objects use dynamic memory allocation of unknown size, the compiler cannot evaluate them at compile time. Polyspace flags initialization of string objects irrespective of whether you specify an initializer.

Troubleshooting

If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

#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 flags the initialization of:

  • global_b by global_a because whether global_b evaluates to a constant at compile time depends on the order in which these variables are initialized.

  • global_name and global_id because the compiler cannot evaluate constructor for string objects at compile time.

  • global_const_c by the extern variable global extern_c because the compiler cannot evaluate extern variables at compile time.

  • obj2, which calls the constructor B::B(), because the constructor is not specified as constexpr.

Polyspace does not flag the initialization of:

  • global_const_b by global_const_a because the compiler can evaluate these objects at compile time regardless of their initialization order.

  • global_const_a and global_a by literals because the compiler can evaluate literals at compile time.

  • Global character pointers and arrays by literal initializers because the compiler can allocate static memory at compile time.

  • obj1, which calls the constructor A::A(), because the constructor is specified as constexpr.

Check Information

Group: Basic concepts
Category: Required, Automated

Version History

Introduced in R2020a