Rule A8-5-0 (required, implementation, automated)
All memory shall be initialized before it is read.
Rationale
Objects with automatic or dynamic storage duration are default-initialized if no initializer is specified. Default initialization produces indeterminate values for objects of neither class nor array types. Default initialization of array types leads to default initialization of each array element. Reading from indeterminate values may produce undefined behavior. Thus, all local variables, member variables, or objects allocated dynamically must be explicitly initialized before their values are read, unless they are of class type or array of non-fundamental type. It is recommended practice to initialize all such objects immediately when they are defined. Note: Zero-initialization will happen before any other initialization for any objects with static or thread-local storage duration. Thus, such objects need not be explicitly initialized.
Example
// $Id: A8-5-0.cpp 307536 2018-02-14 12:35:11Z jan.babst $
#include <cstdint>
#include <string>
static std::int32_t zero; // Compliant - Variable with static storage duration
// is zero-initialized.
void local()
{
std::int32_t a;
// No initialization
std::int32_t b{}; // Compliant - zero initialization
b = a;
// Non-compliant - uninitialized memory read
a = zero; // Compliant - a is zero now
b = a;
// Compliant - read from initialized memory
std::string s; // Compliant - default constructor is a called
// read from s
}
void dynamic()
{
// Note: These examples violate A18-5-2
auto const a = new std::int32_t;
// No initialization
auto const b = new std::int32_t{}; // Compliant - zero initialization
*b = *a;
// Non-compliant - uninitialized memory read
*a = zero; // Compliant - a is zero now
*b = *a;
// Compliant - read from initialized memory
delete b;
delete a;
auto const s =
new std::string; // Compliant - default constructor is a called
// read from *s
delete s;
}
// Members of Bad are default-initialized by the (implicitly generated) default
// constructor. Note that this violates A12-1-1.
struct Bad
{
std::int32_t a;
std::int32_t b;
};
// Compliant - Members of Good are explicitly initialized.
// This also complies to A12-1-1.
struct Good
{
std::int32_t a{0};
std::int32_t b{0};
};
void members()
{
Bad bad; // Default constructor is called, but members a not initialized
bad.b = bad.a; // Non-compliant - uninitialized memory read
bad.a = zero;
// Compliant - bad.a is zero now
bad.b = bad.a; // Compliant - read from initialized memory
Good good; // Default constructor is called and initializes members
std::int32_t x = good.a; // Compliant
std::int32_t y = good.b; // Compliant
}
See also
MISRA C++ 2008 [7]: 8-5-1: All variables shall have a defined value before they are used. HIC++ v4.0 [9]: 8.4.1: Do not access an invalid object or an object with indeterminate value JSF December 2005 [8]: AV Rule 142: All variables shall be initialized before use. SEI CERT C++ Coding Standard [10]: EXP53-CPP: Do not read uninitialized memory C++ Core Guidelines [11]: ES.20: Always initialize an object ISO/IEC 14882:2014 [3]: 8.5: [dcl.init]