Padding issues between Sparc and Intel

Hello,
I'm facing severe structure padding issues when my Solaris C/C++ application that runs on Sparc communicates with the same C/C++ application that runs on Intel. I know that Sparc and Intel use different padding patterns. So when it comes to reading the exchanged structure data, both machines read the wrong data. The structure that is exhanged between the two machines contains both uint32_t and uint64_t variables.
I could add some extra uint32_t 0s in the structure definition in case of Intel but this is not an actual clean solution.

Is there a way to resolve this padding issue?

Thanx in advance.

You should post your question here , it will attract more attention
also you can have look here , here and here

1 Like

Aside from alignment issues, you may also have to consider endianness. Intel x86 is little endian and Sparc may be big endian (some are purely big endian and some are bi).

Regards,
Alister

Hello,
I'm facing structure padding issues when my Solaris 32-bit C/C++ application that runs on Sparc communicates with the same C/C++ application that runs on 32-bit Intel. I know that Sparc and Intel use different padding patterns. So when it comes to reading the exchanged structure data, both machines read the wrong data.

My structure is of the form:

typedef struct {
  uint8_t a;
  uint8_t b;
  uint16_t c;
  uint32_t d;
  uint64_t e;
  struct {
      uint64_t f;
      uint32_t g;
  } inner_struct;
  uint32_t h;
  uint32_t i;
  uint16_t j;
  uint16_t k;
  uint64_t l;
} outter_struct; 

Is there a way to resolve this padding issue?

Thanx in advance.

First, always put the largest elements of your structure first.

Second, what compiler are you using? What compiler options?

Third, have you even looked into the endian differences between SPARC and x86?

You cannot safely pass structures/unions/etc between disparate computing platforms in the way that you seem to expect it to work. Aside from endianness issues, there are structure packing and alignment issues, programming model issues, etc.

This problem has been solved a long time ago. Check out IDL - Interface Description Language, RPC, CORBA, etc.

The padding issue is simple to avoid. Simply do not write/read structs. Instead, write/read each member, recursively when a nested struct is encountered.

Since you're using fixed-width numeric types, implementation-defined size variance is not an issue.

However, you still have to worry about endianness if you're reading/writing multibyte types across different hardware platforms (even when they're running the same operating system). In this case, all members of your struct are simple numeric types (flattening the nested struct), so you may be able to write/read them using the standard ntoh*/hton* libc functions if the c libraries of all relevant platforms provide a 64-bit extension. If no 64-bit version of those functions is available, you could play games with casting, pointers, bitmasks, bitshifting, etc ... to massage the 64-bit types into network byte order. Or, perhaps you could avoid all of the above and use an implementation of XDR (or something similar).

In case you you haven't used them, the keywords 'serialization' and 'marshalling' should be helpful in searching/googling for further information on this topic.

Regards,
Alister

Hi all,

Thank you all for posting. I have dealt with all endianess issues successfully. The thing is that part of code with the nested structs is quite old so writing it is probably the best thing to do. I will re-arrange the structure so that the largest elements are first, as achenle suggests and if this does not work I will try to break the struct to seperate parts

Also, whatever compiler you're using, look at "#pragma align ...." and "#pragma pack ...", as they're both very useful here.

And watch your compilation options, especially those regarding optimizations. One common optimization is placing fields on the "best" alignment, which could easily be different on different hardware. In particular, the Sun/Oracle Studio compiler suite has the "-fast" optimization option, and that implicitly changes data structure alignment and packing.

The quickest way to check if you have a problem is simply to check the size of the structure using sizeof(). If you get different results on SPARC than you do on x86, obviously the structures aren't aligned the same. If you arrange the elements largest-to-smallest and get the same sizes, you almost certainly have an identical layout on both.

Thanks achenle.

I solved my problem in 2 different ways: (1) by inserting, for the INTEL architecture, some extra 32-bit padding members in my struct and (2) by re-aligining my struct members from largest (64-bit) to smallest (8-bit).

I observed that only SPARC performed padding. It was interesting to see that INTEL did not perform any padding at all... This is why I inserted the extra padding in the INTEL struct!

Sorry, but you are still missing the point. You cannot safely pass structures between disparate platforms. You may get away with it on occasion between two particular platforms with two particular compilers but the way you intend doing it is not portable and will come back to bite you.

As other have suggested, check out serialization/deserialization and marshalling/unmarshalling techniques.

You sure can - if you know what you're doing.

Else things wouldn't work - say, like the ENTIRE internet.

What's a TCP packet? A structure. Passed between multiple types of platforms. From the bulk of the available evidence, quite successfully, too.