Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vector of object containing uninitialized value

Does this code cause undefined behaviour:

#include <vector>

struct S
{
    S() {}

    int x;
};

int main()
{
     std::vector<S> vec(5, S());
}

Since S() default-initializes an automatic object, its contents are not zeroed first, so x would be indeterminate. Then the object containing indeterminate value is copied to each vector location.

Motivation: We might expect this to behave the same as std::vector<S> vec(5); which is not UB (since C++11), so this would be an easy mistake to make by accident.

As referred to by Praetorian in comments, prior to C++11 std::vector<S> vec(5); was free to either do 5 default-initializations, or to use the copy-constructor for some or all of the items.

like image 980
M.M Avatar asked Dec 30 '14 03:12

M.M


2 Answers

So taking into account the following comment by the OP:

vector vec(5); is not UB (is it?) and we tend to think that (5) and (5, S()) ought to do the same thing. I could see this mistake being made by accident quite easily.

The question boils down to if:

vector<S> vec(5);

is well defined then why is:

std::vector<S> vec(5, S());

undefined behavior?

If we go to the cppreference section of std::vector::vector we can see in the first case it (since C++11) (emphasis mine):

Constructs the container with count default-inserted instances of T. No copies are made.

while in the second case:

Constructs the container with count copies of elements with value value.

The first case will default construct the elements and no copies are made while in the second case copies will be made and therefore we end up copying x to each element. Since the default constructor of S does not initialize x, it will have an indeterminate value and therefore we have undefined behavior since producing an indeterminate value invokes undefined behavior.

Since C++14 section 8.5 paragraph 12 says:

If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases

with some exceptions in the case of unsigned char which does not apply in this case.

We know that x has an indeterminate value from the same paragraph which says:

When storage for an object with automatic or dynamic storage duration is obtained, the object has an indeterminate value, and if no initialization is performed for the object, that object retains an indeterminate value until that value is replaced

like image 59
Shafik Yaghmour Avatar answered Nov 14 '22 15:11

Shafik Yaghmour


TL;DR Yes, this is Undefined Behavior.


In your code you value-initialize a temporary:

std::vector<S> vec(5, S());
//                    ^^^

From §8.5/10:

An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.

The definition for value-initialization is:

§8.5/8

To value-initialize an object of type T means:

— if T is a (possibly cv-qualified) class type (Clause 9) with either no default constructor (12.1) or a default constructor that is user-provided or deleted, then the object is default-initialized;

— [..]

Value-initialization does not include zero-initialization in this case because S has a user-declared default-constructor. So it is default-constructed.

§8.5/7

To default-initialize an object of type T means:

If T is a (possibly cv-qualified) class type (Clause 9), constructors are considered. The applicable constructors are enumerated (13.3.1.3), and the best one for the initializer () is chosen through overload resolution (13.3). The constructor thus selected is called, with an empty argument list, to initialize the object.

— If T is an array type, each element is default-initialized.

— Otherwise, no initialization is performed.

Since your default-constructor doesn't explicitly initialize x, it keep it's uninitialized garbage value. The default copy-constructor initializes the other elements with these values which is UB.

§8.5/12

If an indeterminate value is produced by an evaluation, the behavior is undefined

like image 31
David G Avatar answered Nov 14 '22 14:11

David G