Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zero-initialize data using value-initialized array

Tags:

c++

c++11

Will the following code correctly zero-initialize the memory returned from malloc?

#include <cstdlib>
#include <new>

int main()
{
    char* p = new (std::malloc(10)) char[10]{};
}
like image 602
template boy Avatar asked Apr 17 '15 19:04

template boy


People also ask

How do you initialize an array with zero values?

The array will be initialized to 0 in case we provide empty initializer list or just specify 0 in the initializer list. Designated Initializer: This initializer is used when we want to initialize a range with the same value. This is used only with GCC compilers.

How do you initialize an array with values?

Initializing an Array with default values To initialize an Array with default values in Java, the new keyword is used with the data type of the Array The size of the Array is then placed in the rectangular brackets. int[] myArr = new int[10]; The code line above initializes an Array of Size 10.

Why do we initialize array with 0?

Initialization to zeros is needed because each element in the array is a counter. If you add 1 (or do other math) to something that is NaN (not a number) or undefined, then you'll either get an error or unreliable results.

Are array values initialized to 0 in Java?

if the elements in the array are integers (int), each element in the array will be automatically initialized to 0. if the elements in the array are Strings, each element will be initialized to the null character (null). if the elements in the array are boolean, each element will be initialized to false.


1 Answers

Yes, it will zero-initialize memory because of the {} at the end of the line, as long as malloc doesn't fail from within the placement new. Here's an alternative version that more completely proves the point.

#include <iostream>
#include <cassert>
#include <new>

char mongo[10];

int main()
{
    for (int i=0; i < 10; ++i)
        mongo[i] = 'a';
    char *p = new (mongo) char[10]{};
    for (int i= 0; i < 10; ++i)
        assert(p[i] == '\0');
}

This program will run and print nothing because the mongo array (aliased by p) is explicitly cleared by the initialization of p. By contrast, if we omit the {} at the end of that line, the program will assert and terminate.

Note that in your version using malloc, you will have to explicitly destroy the object -- that's part of the responsibility that comes with placement new and among the few times in modern C++ where one must explictly call a destructor.

If, as in your particular case, you are allocating memory with malloc() you must issue a corresponding free(p) or your program will leak memory.

The elephant in the room

(Thanks, @TC, for pointing to the big gray thing!) Here's an explanation and example straight from the standard (section 5.3.4):

Example:

new T results in a call of operator new(sizeof(T)),

new(2,f) T results in a call of operator new(sizeof(T),2,f),

new T[5] results in a call of operator new[](sizeof(T)*5+x), and

new(2,f) T[5] results in a call of operator new[](sizeof(T)*5+y,2,f).

Here, x and y are non-negative unspecified values representing array allocation overhead; the result of the new-expression will be offset by this amount from the value returned by operator new[]. This overhead may be applied in all array new-expressions, including those referencing the library function operator new[](std::size_t, void*) and other placement allocation functions. The amount of overhead may vary from one invocation of new to another.

In other words, if you use placement new for a single object, everything is fine and there is no inserted overhead, but if you allocate an array via placement new, there may be overhead, and it might not even be the same size from invocation to invocation.

like image 95
Edward Avatar answered Oct 01 '22 01:10

Edward