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
anddelete
, but here I'm usingmalloc
andfree
. This is necessary because some compilers will pad the data differently whennew
is used, leading to errors in transferring data between different platforms. This doesn't happen withmalloc
.
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!
Answer
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.
No comments:
Post a Comment