Reputation: 10480
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]{};
}
Upvotes: 7
Views: 174
Reputation: 7100
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.
(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 ofoperator new(sizeof(T))
,
new(2,f) T
results in a call ofoperator new(sizeof(T),2,f)
,
new T[5]
results in a call ofoperator new[](sizeof(T)*5+x)
, and
new(2,f) T[5]
results in a call ofoperator 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 operatornew[](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.
Upvotes: 7
Reputation: 137425
This is a very, very bad idea.
Currently, placement array new
, like all array new
expressions, is allowed to add an unspecified amount of overhead. There is no portable way for the program to know how many bytes this overhead is.
Therefore, unless the implementation's array allocation overhead for char[10]
is zero, your code has undefined behavior.
If the pointer points to sufficient memory to accommodate all the array elements plus the unspecified overhead amount (and that's a very big if, since there's no portable way for you to be sure), then the expression will indeed zero-initialize the memory.
Upvotes: 5