Object vector containing uninitialized value

This code invokes undefined behavior:

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

Since S() default - initializes the automatic object, its contents are not reset at first, so x will be undefined. Then the object containing the undefined value is copied to each location of the vector.

Motivation: We could expect this to behave just like std::vector<S> vec(5); that is not UB (since C ++ 11), so it would be easy to make a mistake to do this by accident.

As Praetorian mentioned in the comments, before C ++ 11 std::vector<S> vec(5); it was free to either perform 5 initializations by default, or use a copy constructor for some or all of the elements.

+6
source share
2 answers

So, given the following OP comment:

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

The question boils down to the fact that:

 vector<S> vec(5); 

clearly defined, why:

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

undefined behavior?

If we move on to the cppreference std :: vector :: vector section, we will see this in the first case (starting with C ++ 11) (my attention):

Creates a container with T instances installed by default. No copies .

and in the second case:

Creates a container with copies of elements with a value of value.

In the first case, elements will be built by default, and copies will not be made, and in the second case, copies will be made, and therefore we will end copying x to each element. Since the default constructor of S does not initialize x , it will have an undefined value, and therefore we have undefined behavior, since undefined behavior is called when creating an undefined value.

Since section C ++ 14 8.5 paragraph 12 says:

If an undefined value is obtained by evaluating, the behavior is undefined, except in the following cases:

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

We know that x has an undefined value from the same paragraph, which reads:

When storing for an object with automatic or dynamic storage duration, the object has an undefined value, and if not, the object is initialized, this object retains an undefined value until this value is replaced

+4
source

TL DR Yes, this is Undefined Behavior.


In your code, you initialize the time value:

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

From § 8.5 / 10:

An object whose initializer is an empty set of brackets, i.e. () must be initialized with a value.

Value initialization definition:

§8.5 / 8

To initialize a value of an object of type T means:

- if T is a (possibly cv-qualified) type class (section 9) without a default constructor (12.1) or a default constructor that is provided or deleted by the user, then the object is initialized by default;

- [..]

Initialization of values ​​does not include zero initialization in this case, because S has a default constructor declared by the user. Thus, it is built by default.

§8.5 / 7

By default, initializing an object of type T means:

- If T is a (possibly cv-qualified) class type (clause 9), constructors are considered. The corresponding constructors are listed (13.3.1.3), and the best for the initializer () is selected by overload resolution (13.3). The constructor selected in this way is called with an empty list of arguments to initialize the object.

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

- Otherwise, initialization fails.

Since your default constructor does not explicitly initialize x , it saves the uninitialized garbage value. The default constructor initializes other elements with these values, which are UB.

§8.5 / 12

If an undefined value is obtained by evaluating, the behavior is undefined

+2
source

Source: https://habr.com/ru/post/980288/


All Articles