I recently ran into an issue where it appeared IPC using shared memory broke between two applications. When compiled with the same compiler (gcc11 or clang14) they could communicate successfully, but with different compilers the communication broke down.
I strongly suspect that the sizes and/or offsets of the objects being written to shared memory are different depending on the compiler version.
Is there an easy way to verify this for a large number of structs?
As a very first step, add static_assert(sizeof(FooStruct)==16);
to each struct. Pick a size that works on your preferred platform. Now you'll get some breaks when things go poorly, which is better than no breaks!
You'll have to write the sizes manually, hard code them in the file.
Then you'll get a size mismatch. This will not catch offset mismatches on members, but those are (honestly) rarer, as usually an offset mismatch leads to a size difference (not always).
Once you have done this first step, start writing code to explicitly serialize wire types. Have your wire protocol force going through such serialization, possibly through calling an ADL based function.
You can do the first step of this and implement bad binary serialization on existing types you are sending over the wire, and then incrementally make it not suck and be safer.
Other good early steps are checking for POD-ness (well, the sub-traits), and writing code that breaks classes down into members and serializes the members (there are some tricks you can do to partially automate this by hacking reflection into C++).
The point is you can make it better long before it is good, because good will take a bunch of work.