跨拱上的字节填充问题
我注意到我的程序结构上的 sizzeof() 在 x86 和 x64 平台上是不同的。这是因为字节填充。由于一项要求(我的应用程序在跨拱 m/c 之间进行对话),我需要确保目标应该获得与发送者通过 nammedpipe 发送的结构大小相同的结构(在我的情况下,我无法再次读取管道)剩余数据..)。如果我可以安全地禁用/启用填充或在该结构上使用 sizeof() 运算符之前剥离填充字节,我需要一种 C++ 方法。
谢谢..
[编辑|结论]:仅供其他尝试寻求类似问题解决方案的人参考。尝试了很多愚蠢的方法来解决这个问题,但这里提到的一个可能的解决方案以另一种方式产生了问题,即调试耗时。我能找到的解决这个问题的最佳选择是使用序列化和反序列化方法,如下面提到的“R..”。
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 solution 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果您在结构之前输入#pragma pack(1),它应该禁用填充。这适用于 Visual Studio 和 gcc。您可能还想使用 #pragma pack(push) 和 #pragma pack(pop) 来保存和恢复以前的填充规则。
例如:
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:
避免编写使用结构/联合的 sizeof 的代码。为了可移植性,请对各个成员使用 sizeof :
Avoid writing code that is using sizeof of a struct/union. For portability, use sizeof on the individual members instead:
你使用什么编译器?您可以使用 GCC 的
packed
属性告诉编译器不要在结构中添加任何填充。其他编译器可能也有类似的功能。http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html
aligned
属性也可能对您有帮助。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.请记住还要确保您使用的是与架构无关的结构元素 - 如果两个不同的架构具有不同大小的 int,那么删除填充将无济于事。尝试使用 stdint.h 类型代替,例如。 int32_t 而不是 int。
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.
其他人已经指出,除了填充之外,类型的大小可能因架构而异。除此之外,字节序也可能有所不同(32 位和 64 位 Intel 之间不存在这种情况,但如果其他人抛出它,则可能会成为一个问题)。
所以序列化是一个好主意。基本上只需为每种架构创建一个用于写入的函数和一个用于读取的函数。
write 函数将写入每个结构成员的每个相关字节,其中成员按已知顺序写入,每个成员的字节也按已知顺序(例如,最重要的在前)。如果类型的大小因平台而异,请写入所有平台支持的类型的字节数。
读取函数应该执行与写入函数相反的操作,并将序列化数据中未包含的所有字节归零。这些函数并不难编写,并且使用它们使得基本类型的填充、字节顺序和(通常)大小变得无关紧要。
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.