3
votes

With regard to alignment, there is something I don't understand about the difference between an explicit call to T* t = (T*) ::operator new(sizeof(T)) and T* t = (T*)new char[sizeof(T)], where T is a C-like struct.

In the book "C++ Solutions Companion to The C++ Programming Language, Third Edition" (see exercise 12.9), the author says: "Note that one should not use the expression new char[n] to allocate raw memory because that memory may not satisfy the alignment requirements of a T, while an explicit call of the global operator new is guaranteed to yield storage that is sufficiently aligned for any C++ object.". This is also stated in an article I read on internet: http://www.scs.stanford.edu/~dm/home/papers/c++-new.html (see the "delete vs. delete[] and free" paragraph).

On the other hand, in my previous post Data alignment in C++, standard and portability a guy quoted the standard, plus a note at the end of the quote which contradicts the above people:

"A new-expression passes the amount of space requested to the allocation function as the first argument of type std::size_t. That argument shall be no less than the size of the object being created; it may be greater than the size of the object being created only if the object is an array. For arrays of char and unsigned char, the difference between the result of the new-expression and the address returned by the allocation function shall be an integral multiple of the strictest fundamental alignment requirement (3.11) of any object type whose size is no greater than the size of the array being created. [ Note: Because allocation functions are assumed to return pointers to storage that is appropriately aligned for objects of any type with fundamental alignment, this constraint on array allocation overhead permits the common idiom of allocating character arrays into which objects of other types will later be placed. — end note ]"

I am confused. Could you please tell me who is right here according to the standard and, in case, why is ::operator new() different from new char[]?

3

3 Answers

2
votes

That's right, new char[n] delegates to operator new[](size_t), see 5.3.4 "New" §8:

A new-expression obtains storage for the object by calling an allocation function [...] If the allocated type is an array type, the allocation function's name is operator new[]

Hence, there is absolutely no way the former could somehow yield "less aligned" memory than the latter.

Sadly, when it comes to technical details, most C++ books out there just plain suck.

1
votes

C++98 §3.7.3.1/2, about allocation functions:

The pointer returned shall be suitably aligned so that it can be converted to a pointer of any complete object type and then used to access the object or array in the storage allocated

Together with your quote of §5.3.4/10 about new-expressions, "A new-expression passes the amount...", this means new char[n] can't offer weaker alignment guarantees, it can't be less aligned.

Cheers & hth.,

0
votes

The confusion is between different versions of the standard. The older standard did not make the guarentee about new char[n] and the newer one does.

Note the bit in both cases where new char[n] might NOT return the same pointer it got back from the underlying operator new(size_t) -- that's because when allocating an array, the runtime may use the space at the beginning of the allocated block (the space between what operator new(size_t) returned and what new char[n] returns) to store the size of the array -- and that size might not require the full worst-case alignment padding. An implementation is not required to do this -- it might note that, since char has no destructor, it doesn't need to record the size of the array to know how many destructor calls to make when delete[] is called. But an implementation is free to treat all arrays uniformly.