Byte padding issue on cross arch
I have noticed that sizzeof() on my program structure is different on x86 and x64 platform. This is becaue of bytes padding. Due to one requirement (where my application talks between cross arch m/c), i need to make sure that target should get the same size of structure what sender had send through a nammedpipe (in my case, i can not read pipe again for remaining data..). I need a way in C++ if i can disable/enable padding safely or strip padding bytes before using sizeof() operator on that structure.
Thanks..
[EDIT | CONCLUSION]: just an input for others who try to seek solution for similar issue. Tried a lot many stupid things to get around this issue but one possible solutio开发者_开发问答n mentioned here created the problem in another way, debugging of which time-taking. The best option to this problem i could find out is to use serialization and deserialization methods as 'R..' has mentioned below.
If you type #pragma pack(1) before your structure it should disable padding. This works on both visual studio and gcc. You probably also want to use #pragma pack(push) and #pragma pack(pop) to save and restore the previous padding rules. For example:
#pragma pack(push)
#pragma pack(1)
struct
{
...
};
#pragma(pop)
Avoid writing code that is using sizeof of a struct/union. For portability, use sizeof on the individual members instead:
const int struct_size = sizeof(x.member1) + sizeof(x.member2) + ...;
What compiler are you using? You can use GCC's packed
attribute to tell the compiler to not add any padding in your struct. Other compilers probably have a similar feature.
http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html
The aligned
attribute might help you as well.
Remember to also make sure that you are using arch-independent elements of structure - if two different arch's have - say - different size of int, then removing padding will not help. Try to use stdint.h types instead eg. int32_t instead of int.
Others have already pointed out that in addition to padding, the sizes of the types may vary between architectures. In addition to that, endianness could vary too (not between 32 and 64 bit Intel, but if others are thrown it it could be an issue).
So serialization is a good idea. Basically just create a function for writing and one for reading for each architecture.
The write function would write each relevant byte of each structure member, with the members written in a known order, and the bytes of each member also in a known order (say, most significant first). If the sizes of a type vary between platforms, write as many bytes of the type as all platforms will support.
The read function should do the reverse of what the write function does, and zero any bytes that aren't included in the serialized data. The functions aren't hard to write, and using them makes the padding, endianness and (often) sizes of basic types irrelevant.
精彩评论