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
Storing of pointer addresses
A large number of errors during the migration on 64-bit systems are related to the change of a pointer size in relation to the size of usual integers. In the environment with the data ILP32 usual integers and pointers have the same size. Unfortunately the 32-bit code is based on this supposition everywhere. Pointers are often casted to int, unsigned int and other types improper to fulfill address calculations.
You should understand exactly that one should use only memsize types for integer pointers form. Preference should be given to uintptr_t type for it shows intentions more clearly and makes the code more portable saving it from changes in future
Let’s look at two small examples.
1) char *p; p = (char *) ((int)p & PAGEOFFSET); |
2) DWORD tmp = (DWORD)malloc(ArraySize); ... int *ptr = (int *)tmp; |
The both examples do not take into account that the pointer size may differ from 32-bits. They use the explicit type conversion which truncates high bits in the pointer and this is surely a mistake on the 64-bit system. Here are the corrected variants which use integer memsize type intptr_t and DWORD_PTR to store pointer addresses:
1) char *p; p = (char *) ((intptr_t)p & PAGEOFFSET); |
2) DWORD_PTR tmp = (DWORD_PTR)malloc(ArraySize); ... int *ptr = (int *)tmp; |
The danger of the two examples studied is that the fail in the program may be found much time later. The program may work absolutely correctly with a small data size on the 64-bit system while the truncated addresses lie in first 4 Gb of memory. And then on launching the program for large production aims there will be the memory allocation out of first 4 Gb. The code given in the examples will cause an undefined behavior of the program on the object out of first 4 Gb while processing the pointer.
The following code won’t hide and will show up at the first execution.
void GetBufferAddr(void **retPtr) { ... // Access violation on 64-bit system *retPtr = p; } unsigned bufAddress; GetBufferAddr((void **)&bufAddress); |
The correction is also in the choice of the type capable to store the pointer.
uintptr_t bufAddress; GetBufferAddr((void **)&bufAddress); //OK |
There are situations when storing of the pointer address into a 32-bit type is just necessary. Mostly such situations appear when it is necessary to work with old API functions. For such cases one should resort to special functions LongToIntPtr, PtrToUlong etc.
In the end I’d like to mention that it will be a bad style to store the pointer address into types which are always equal 64-bits. One will have to correct the code shown further again when 128-bit systems will appear.
PVOID p; // Bad style. The 128-bit time will come. __int64 n = __int64(p); p = PVOID(n); |
Related articles
Related discussion
-
WinGDB - Linux debugging under Visual Studio
by WinGDB (0 replies)
-
Regarding Serial port communication
by raghu550 (0 replies)
-
Convert C++ code to VB6
by mawcot (4 replies)
-
How to create a games like FIFA08
by mawcot (0 replies)
-
Binary Studio | software development outsourcing Ukraine
by shane124 (4 replies)
Related podcasts
-
Interview with Shawn Burke on Microsoft's .NET Source Code Release
Scott and Carl talk with Shawn Burke on the culmination of his many-year-old plan to get parts of the source of the .NET Framework released. With Visual Studio 2008, a simple process will allow developers to STEP INTO the .NET Framework Source from the IDE. This'll be a great debugging and learni...
This thread is for discussions of Typical errors of porting C++ code on the 64-bit platform.