Library tutorials & articles
Typical errors of porting C++ code on the 64-bit platform
- Introduction
- Off-warnings
- Use of the functions with a variable number of arguments
- Magic numbers
- Bit shifting operations
- Storing of pointer addresses
- Memsize types in unions
- Change of an array type
- Virtual functions with arguments of memsize type
- Serialization and data exchange
- Pointer address arithmetic
- Arrays indexing
- Mixed use of simple integer types and memsize types
- Implicit type conversions while using functions
- Overload functions
- Data alignment
- The use of outdated functions and predefined constants
- Explicit type conversions
- Error diagnosis
- Unit test
- Code review
- Built-in means of compilers
- Static analyzers
- Conclusion
- Resources
Magic numbers
In the low-quality code there are often magic numbers the mere presence of which is dangerous. During the migration of the code on the 64-bit platform these magic numbers may make the code inefficient if they participate in operations of calculation of address, objects size or bit operations.
Table N2 contains basic magic numbers which may influence the workability of an application on a new platform.
Value Description 4 Number of bytes in a pointer type 32 Number of bits in a pointer type 0x7fffffff The maximum value of a 32-bit signed variable. Mask for zeroing of the high bit in a 32-bit type. 0x80000000 The minimum value of a 32-bit signed variable. Mask for allocation of the high bit in a 32-bit type. 0xffffffff The maximum value of a 32-bit variable. An alternative record -1 as an error sign. |
You should study the code thoroughly in search of magic numbers and replace them with safe numbers and expressions. To do so you can use sizeof() operator, special values from <limits.h>, <inttypes.h> etc.
Let’s look at some errors related to the use of magic numbers. The most frequent is a record of number values of type sizes.
1) size_t ArraySize = N * 4; intptr_t *Array = (intptr_t *)malloc(ArraySize); |
2) size_t values[ARRAY_SIZE]; memset(values, ARRAY_SIZE * 4, 0); |
3) size_t n, newexp; n = n >> (32 - newexp); |
Let’s suppose that in all cases the size of the types used is always 4 bytes. The correction of the code is in the use of sizeof() operator.
1) size_t ArraySize = N * sizeof(intptr_t);
intptr_t *Array = (intptr_t *)malloc(ArraySize);
|
2) size_t values[ARRAY_SIZE]; memset(values, ARRAY_SIZE * sizeof(size_t), 0); or memset(values, sizeof(values), 0); //preferred alternative |
3) size_t n, newexp;
n = n >> (CHAR_BIT * sizeof(n) - newexp);
|
Sometimes we may need a specific number. As an example let’s take the size_t where all the bits except 4 low bits must be filled with ones. In a 32-bit program this number may be declared in the following way.
// constant '1111..110000' const size_t M = 0xFFFFFFF0u; |
This is the incorrect code in the case of the 64-bit system. Such errors are very unpleasant because the record of magic numbers may be carried out in different ways and the search for them is very laborious. Unfortunately, there is no other way except to find and to correct this code using #ifdef or a special macro.
#ifdef _WIN64 #define CONST3264(a) (a##i64) #else #define CONST3264(a) (a) #endif const size_t M = ~CONST3264(0xFu); |
Sometimes as an error code or other special marker "-1" value is used which is written as "0xffffffff". On the 64-bit platform the recorded expression is incorrect and we should evidently use -1 value. An example of the incorrect code using 0xffffffff value as an error sign.
#define INVALID_RESULT (0xFFFFFFFFu) size_t MyStrLen(const char *str) { if (str == NULL) return INVALID_RESULT; ... return n; } size_t len = MyStrLen(str); if (len == (size_t)(-1)) ShowError(); |
To be on the safe side, let’s make sure that you know clearly what is the result of "(size_t)(-1)" value on the 64-bit platform. You may make a mistake saying value 0x00000000FFFFFFFFu. According to C++ rules -1 value turns into a signed equivalent of a higher type and then into an unsigned value:
int a = -1; // 0xFFFFFFFFi32 ptrdiff_t b = a; // 0xFFFFFFFFFFFFFFFi64 size_t c = size_t(b); // 0xFFFFFFFFFFFFFFFui64 |
Thus "(size_t)(-1)" on the 64-bit architecture is represented by 0xFFFFFFFFFFFFFFFui64 value which is the highest value for the 64-bit size_t type.
Let’s return to the error with INVALID_RESULT. The use of the number 0xFFFFFFFFu causes the failure of the execution of "len == (size_t)(-1)" condition in a 64-bit program. The best solution is to change the code in such a way that it doesn’t need special marker values. If you cannot refuse them for some reason or think it unreasonable to correct the code fundamentally just use fair value -1.
#define INVALID_RESULT (size_t(-1))
...
|
Related articles
Related discussion
-
Microsoft MVP Donald Belcham to Speak on Visual Studio, C# vNext, Aspect Oriented Programming, Live Mesh
by Shaggy123 (0 replies)
-
Using Microsoft Visual Studio to creat a C# Project that nests DLL source as well.
by Complete (0 replies)
-
Adobe Flex reaches out to .NET developers
by ranganathanmca (1 replies)
-
how to write code in VB 5 for printronix printer
by yan_azna (0 replies)
-
conting repeated words
by Slicksim (2 replies)
Related podcasts
-
Looking into the C# Crystal Ball with Charlie Calvert and Bill Wagner
One of the most exciting announcements from PDC was the news about C# 4.0 and Visual Studio 2010. With all the excitement and discussion throughout the event about these new developer tools, we reached out to two experts in the fields. Charlie Calvert and Bill Wagner sat down with Keith and Woody...
Events coming up
-
Dec
6
Developing AJAX Web Applications with Castle Monorail
London, United Kingdom
Monorail is the model-view-controller engine of the Castle Project, bringing many of the best ideas of Ruby on Rails to the .NET world. In this talk, David De Florinier and Gojko Adzic show how Monorail makes it easy to develop .NET based AJAX applications, and how to use the Castle Project to build Web 2.0 applications effectively. Come to this session if you are a .NET web developer. Everyone is welcome!
This thread is for discussions of Typical errors of porting C++ code on the 64-bit platform.