Malloc vs new
I'm reviewing someone else's C++ code for our project that uses MPI for high-performance computing (10^5 - 10^6 cores). The code is intended to allow for communications between (potentially) different machines on different architectures. He's written a comment that says something along the lines of:
We'd normally use new
and delete
, but here I'm using malloc
and free
. This is necessary because some compilers will pad the data differently when new
is used, leading to errors in transferring data between different platforms. This doesn't happen with malloc
.
This does not fit with anything I know from standard new
vs malloc
questions.
What is the difference between new/delete and malloc/free? hints at the idea that the compiler could calculate the size of an object differently (but then why does that differ from using sizeof
?).
malloc & placement new vs. new is a fairly popular question but only talks about new
using constructors where malloc
doesn't, which isn't relevant to this.
how does malloc understand alignment? says that memory is guaranteed to be properly aligned with either new
or malloc
which is what I'd previously thought.
My guess is that he's misdiagnosed his own bug some time in the past and deduced that new
and malloc
give different amounts of padding, which I think probably isn't true. But I can't find the answer with Google or in any previous question.
Help me, StackOverflow, you're my only hope!
IIRC there's one picky point. malloc
is guaranteed to return an address aligned for any standard type. ::operator new(n)
is only guaranteed to return an address aligned for any standard type no larger than n, and if T
isn't a character type then new T[n]
is only required to return an address aligned for T
.
But this is only relevant when you're playing implementation-specific tricks like using the bottom few bits of a pointer to store flags, or otherwise relying on the address to have more alignment than it strictly needs.
It doesn't affect padding within the object, which necessarily has exactly the same layout regardless of how you allocated the memory it occupies. So it's hard to see how the difference could result in errors transferring data.
Is there any sign what the author of that comment thinks about objects on the stack or in globals, whether in his opinion they're "padded like malloc" or "padded like new"? That might give clues to where the idea came from.
Maybe he's confused, but maybe the code he's talking about is more than a straight difference between malloc(sizeof(Foo) * n)
vs new Foo[n]
. Maybe it's more like:
malloc((sizeof(int) + sizeof(char)) * n);
vs.
struct Foo { int a; char b; }
new Foo[n];
That is, maybe he's saying "I use malloc", but means "I manually pack the data into unaligned locations instead of using a struct". Actually malloc
is not needed in order to manually pack the struct, but failing to realize that is a lesser degree of confusion. It is necessary to define the data layout sent over the wire. Different implementations will pad the data differently when the struct is used.
Your colleague may have had new[]/delete[]
's magic cookie in mind (this is the information the implementation uses when deleting an array). However, this would not have been a problem if the allocation beginning at the address returned by new[]
were used (as opposed to the allocator's).
Packing seems more probable. Variations in ABIs could (for example) result in a different number of trailing bytes added at the end a structure (this is influenced by alignment, also consider arrays). With malloc, the position of a structure could be specified and thus more easily portable to a foreign ABI. These variations are normally prevented by specifying alignment and packing of transfer structures.
The layout of an object can't depend on whether it was allocated using malloc
or new
. They both return the same kind of pointer, and when you pass this pointer to other functions they won't know how the object was allocated. sizeof *ptr
is just dependent on the declaration of ptr
, not how it was assigned.
上一篇: 标准C ++中的垃圾收集是否自动?
下一篇: Malloc vs新