Search code examples
c++11gccstructinitializationlist-initialization

struct uninitialization issue in c++


I have following three structs definitions, for SA, SBad, SC, I simplified name and members to just demonstrate the issue.

 struct SA {
     int snap;
 };

 template <int W> class VString
 {
     char data[W];
   public:
     VString() { }
 };

 struct SBad {
     VString<9> s;
     int i;
 };

 struct SC {
     int inst;
 };

And I have a containing struct to hold data from the network which consists of the above structures:

 struct S {
     std::vector<SA>           m_a;
     SBad                      m_bad;
     std::vector<SC>           m_c;
 };

And in the code I need to reset struct frequently, with:

// data member
S m_s;
// member function
void clear() {
   m_s.m_bad   = {};
}

I'm using gcc version 7.3.1. With debug build, this works fine, with release build, it fails with:

error: '<anonymous>' is used uninitialized in this function [-Werror=uninitialized]

The gcc flag is:

-std=c++11 -O3 -Werror -Wall

Why is this error, it is a defined way of initialising data to zero, right? If I change to :

void clear() {
    SA sa{};
    m_s.a = sa;
    m_s.b = {};
    ...
}

instead, the release build will succeed.

UPDATE:

I created a minimum working test case to show the issue.


Solution

  • You can only use curly-brace initialization with "Aggregates". Quoting the standard:

    An aggregate is an array or a class (clause 9) with no user-declared constructors (12.1), no private or protected non-static data members (clause 11), no base classes (clause 10), and no virtual functions (10.3).

    ...

    When an aggregate is initialized the initializer can contain an initializer-clause consisting of a brace-enclosed, comma-separated list of initializer-clauses for the members of the aggregate, written in increasing subscript or member order. If the aggregate contains subaggregates, this rule applies recursively to the members of the subaggregate.

    In your case, SBad is not an aggregate because SBad::s of type VString is not an aggregate since you defined a constructor for VString. To get your code to work, drop the constructor of VString:

     template <int W> class VString {
         char data[W];
     };
    

    Try it here: https://godbolt.org/z/TTonr6