c++chardynamic-memory-allocationnew-operatordynamic-arrays

Issue with aggregate initialization with the new operator


The following two codes behave as expected:

char* test1 = new char[20]{"abc"};
cout << test1;

Outputs: abc

int size = 20;
char* test1 = new char[size]{'a','b','c'};
cout << test1;

Outputs: abc

But, the following code behaves unexpectedly in gcc and MSVC, while not in clang:

int size = 20;
char* test1 = new char[size]{"abc"};
cout << test1;

Outputs: random values

Why does it not output abc like the other examples?


Solution

  • This is clearly a GCC and MSVC bug, although I could not find an existing bug report for it. Clang seems to handle it properly.

    Note that there exists wording to cover this case in [expr.new] p8:

    If the expression in a noptr-new-declarator is present, it is implicitly converted to std​::​size_t. The value of the expression is invalid if

    • [...]
    • the new-initializer is a braced-init-list and the number of array elements for which initializers are provided (including the terminating '\0' in a string-literal ([lex.string])) exceeds the number of elements to initialize.

    What you are doing is expected and valid; the expression size is present, and "abc" only provides an initializer for four elements (including the terminating '\0'), which does not exceed the 20 elements you're constructing.

    The initialization follows the rules in [dcl.init.string], which covers both "abc" and {"abc"}. The remaining 16 elements of the array should be zero.

    Workaround

    You should consider using std::string or performing the initialization in two steps:

    1. new char[size]{}, leaving everything zero initially
    2. std::memcpy the string literal into the char*