Typical errors of porting C++ code on the 64-bit platform

Memsize types in unions

The peculiarity of a union is that for all members of the union the same memory area is allocated that is they overlap. Although the access to this memory area is possible with the use of any of the elements the element for this aim should be chosen so that the result won’t be senseless.

One should pay attention to the unions which contain pointers and other members of memsize type.

When there is a necessity to work with a pointer as an integer sometimes it is convenient to use the union as it is shown in the example, and work with the number form of the type without using explicit conversions.

union PtrNumUnion {
  char *m_p;
  unsigned m_n;
} u;

u.m_p = str;
u.m_n += delta;

This code is correct on 32-bit systems and is incorrect on 64-bit ones. Changing member m_n on the 64-bit system we work only with a part of the m_p. We should use the type which will correspond to the pointer size.

union PtrNumUnion {
  char *m_p;
  size_t m_n; //type fixed
} u;

Another frequent use of the union is in the presentation of one member as an addition of other smaller ones. For example, we may need to split the value size_t type into bytes to carry out the table algorithm of calculation of the number of zero bits in a byte.

union SizetToBytesUnion {
  size_t value;
  struct {
    unsigned char b0, b1, b2, b3;
  } bytes;
} u;
   
SizetToBytesUnion u;
u.value = value;
size_t zeroBitsN = TranslateTable[u.bytes.b0] +
                   TranslateTable[u.bytes.b1] +
                   TranslateTable[u.bytes.b2] +
                   TranslateTable[u.bytes.b3];

Here it is a fundamental algorithmic error which consists in the supposition that size_t type consists of 4 bytes. The possibility of the automatic search of algorithmic errors is hardly possible but we can provide the search of all the unions and check the presence of memsize types in them. Having found such a union we can find an algorithmic error and overwrite the code in the following way.

union SizetToBytesUnion {
  size_t value;
  unsigned char bytes[sizeof(value)];
} u;
   
SizetToBytesUnion u;
u.value = value;
size_t zeroBitsN = 0;
for (size_t i = 0; i != sizeof(bytes); ++i)
  zeroBitsN += TranslateTable[bytes[i]];

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Beware of bugs in the above code; I have only proved it correct, not tried it.” - Donald Knuth