Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

initialize array, placement new, read variables, defined behavior?

given a class who's only member is a char[10], that has no inheritance nor virtual members, that has a constructor that does not mention the array in any way (such that it gets default-initialization -> no initialization, like so:

class in_place_string {
    char data[10];

    static struct pre_initialized_type {} pre_initialized;
    in_place_string(pre_initialized_type) {}  //This is the constructor in question

    in_place_string() :data() {} //this is so you don't yell at me, not relevent
};

Is it defined behavior to placement-new this class into a buffer that already has data, and then read from the array member?

int main() {
    char buffer[sizeof(in_place_string)] = "HI!";
    in_place_string* str = new(buffer) in_place_string(in_place_string::pre_initialized);
    cout << str->data; //undefined behavior?
}

I'm pretty sure it's not well defined, so I'm asking if this is implementation defined or undefined behavior.

like image 895
Mooing Duck Avatar asked May 24 '26 05:05

Mooing Duck


2 Answers

You're not performing a reinterpret_cast (which wouldn't be safe, since the class has non-trivial initialization); you're creating a new object whose member is uninitialized.

Performing lvalue->rvalue conversion on an uninitialized object gives an indeterminate value and undefined behavior. So is the object uninitialized?

According to 5.3.4 all objects created by new-expression have dynamic storage duration. There's no exception for placement new.

Entities created by a new-expression have dynamic storage duration

And then 8.5 says

If no initializer is specified for an object, the object is default-initialized. 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 (5.17). [ Note: Objects with static or thread storage duration are zero-initialized, see end note ] If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases:

and the following cases permit only unsigned char, and even then the value is not useful.

In your case the new object has dynamic storage duration (!) and its members for which no initialization is performed have indeterminate value. Reading them gives undefined behavior.

like image 194
Ben Voigt Avatar answered May 26 '26 18:05

Ben Voigt


I think the relevant clause is 8.5 [dcl.init] paragraph 12:

If no initializer is specified for an object, the object is default-initialized. 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 (5.17). [ Note: Objects with static or thread storage duration are zero-initialized, see 3.6.2. —end note ] If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases:

  • If an indeterminate value of unsigned narrow character type (3.9.1) is produced by the evaluation of:
    • the second or third operand of a conditional expression (5.16),
    • the right operand of a comma expression (5.18),
    • the operand of a cast or conversion to an unsigned narrow character type (4.7, 5.2.3, 5.2.9, 5.4), or
    • a discarded-value expression (Clause 5), then the result of the operation is an indeterminate value.
  • If an indeterminate value of unsigned narrow character type is produced by the evaluation of the right operand of a simple assignment operator (5.17) whose first operand is an lvalue of unsigned narrow character type, an indeterminate value replaces the value of the object referred to by the left operand.
  • If an indeterminate value of unsigned narrow character type is produced by the evaluation of the initialization expression when initializing an object of unsigned narrow character type, that object is initialized to an indeterminate value.

I don't think any of the exception applies. Since the value is read before being initialized after the object is constructed, I think the code results in undefined behavior.

like image 31
Dietmar Kühl Avatar answered May 26 '26 19:05

Dietmar Kühl