I have two processes P1 and P2 in my project. They use boost::interprocess::shared_memory to create a shared memory segment that is properly working (no problem with synchronization). My use-case consists of sending a POD type (a trivially copyable type) from P1 to P2. Let's say the POD type looks like:
struct Widget
{
char val;
int length;
}
I kind of thought that would be easy, and came up with an approach which seems generic for all POD types:
Create a char buff[MAX_SIZE] in shared memory. Subsequently do:
// P1
Rectangle R = {'a', 4};
memcpy(pointer_to_shared_memory, &R, sizeof(R));
// P2
Rectangle R;
memcpy(&R, pointer_to_shared_memory, sizeof(R));
// use R
What bugs me, even if the schema of the object doesn't change, what happens to the default padding that compiler introduces during the compilation of P1 and P2 separately? Although P1 and P2 would be compiled under similar conditions (build flags etc), as well on the same systems, same gcc versions, I still can't leave the padding requirements to gcc, which it would perform at will on two separate scenarios.
For instance, here, I am expecting both P1 and P2 to have a representation of Widget as:
v---
llll
where v is char val, and l is length (a total 8 bytes). My pod may contain uint8, unint16 etc, and it will grow complex overtime. I have a feeling I can't rely on compiler to fix the same padding in memory for two different processes, even though their schema is fixed in source code.
Is there a way, can I guarantee that padding will also be consistent and will be taken care of by the compiler in consistent manner, if the schema is the same in both P1 and P2? I don't want to use pragma or pack preprocessors, since they will limit the type of PODs that I could send over.
Does a serialization library like flatbuffers take care of all of this, and I must use one for this? (I hope not! I don't want to introduce the extra overhead of serialzing/deserializing objects for a POD type)
The struct layout/amount of padding is not arbitrary and will not differ from run to run of the compiler. If it did, separate compilation would be impossible, never mind IPC. Imagine if Widget was defined in a header included in two separate files. It would not be ok for the compiler to vary the padding between compiling the two different files. Any function in libc that took a struct (eg lstat) would be useless if padding/layout wasn’t consistent.