Change of type alignment and the consequences

When porting software one of the task a developer faces is to change types’ sizes and rules of their alignments.

Once my attention was attracted by a message in RSDN forum:

Today I have faced a problem in Linux. There is a data structure consisting of several fields: 64-bit double, 8 unsigned char and one 32-bit int. Altogether it is 20 bytes (8 + 8*1 + 4). On 32-bit systems sizeof is 20 bytes and everything is OK. But on the 64-bit Linux sizeof returns 24 bytes. That is, an alignment at the 64-bit border takes place.

After that the author dwells upon data compatibility and asks for advice how to pack data in the structure. But at the moment we are not interested in this. What we are interested in is that there is a new type of errors which can occur when porting applications on a 64-bit system.

It is clear and common that when sizes of fields in a structure change, the size of the structure itself changes because of this too. But this is a different case. The size of the fields remains the same but the size of the structure will change too due to different alignment rules. This behavior can lead to various errors, for example, incompatibility of the formats of the data being saved.

I took an example of the code printing types’ sizes and alignment from the article “C++ data alignment and portability” [1]. I’ve modified it a bit for Visual Studio and got this program:

#include <iostream>
using namespace std;
template <typename T>
void print (char const* name)
{
  cerr << name
       << " sizeof = " << sizeof (T)
       << " alignof = " << __alignof (T)
       << endl;
}
int _tmain(int, _TCHAR *[])
{
  print<bool>        ("bool          ");
  print<wchar_t>     ("wchar_t       ");
  print<short>       ("short int     ");
  print<int>         ("int           ");
  print<long>        ("long int      ");
  print<long long>   ("long long int ");
  print<float>       ("float         ");
  print<double>      ("double        ");
  print<long double> ("long double   ");
  print<void*>       ("void*         ");
}

I compared the data I’d got with the data described in the article “C++ data alignment and portability” for GNU/Linux systems and now give them in Table 1.

image1

Let’s study this table. Pay attention to the marked cells relating to long int and double. These types’ sizes don’t depend on the architecture’s size and therefore don’t change. Both on 32-bit and 64-bit systems their size is 8 byte. But alignment is different for 32-bit and 64-bit systems. It can cause change of the structure’s size.

In Windows systems, there are no such problems with alignment change. Pay attention that alignment of all the types doesn’t change or changes together with the type’s size. That is good – Windows developers have one potential problem off.

References

  1. Boris Kolpackov. C++ data alignment and portability.
    http://www.codesynthesis.com/~boris/blog/2009/04/06/cxx-data-alignment-portability/

Author: Andrey Karpov

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s