For many developers, the task of moving an application from 32-bits to 64-bits
isn't scary; the problem is one of not knowing where to begin.
This article contains 24 items you should consider before making the move.
Each consideration reviews a different aspect of typical applications; the article
doesn't consider a particular programming language or platform (AMD also makes
a considerable number of solutions available on its Developer Central Web site.
I'm assuming that you're developing applications and not device drivers or operating
system elements, because these low level elements require a great deal of care
to port. In addition, I tested these ideas using newer programming languages
such as those that depend on the .NET Framework or Java. Most of the ideas will
also work with older languages, but you may find that you have to perform some
additional work.
1. Verify Your Compiler and Library Support
A simple problem with 64-bit development today is that many developers don't
know that they can create a 64-bit application for their AMD processor with
their current compiler. Many development environments have 64-bit support, but
don't install the support by default; you must perform a separate installation.
However, having the required templates and project files is only a first step.
You must also ensure that the development environment has the required library
support and that you install it (often a separate step from installing the 64-bit
development environment support).
2. Use 32-bit Libraries with Care
You might find it necessary to use a 32-bit library with your application when
a 64-bit equivalent doesn't exist. Since 32-bit and 64-bit code can't coexist
in the same process, 64-bit applications can't interoperate with 32-bit libraries
and vice versa, without some type of inter-process marshalling between the two
environments. When working with programming languages like C# or Visual Basic,
the marshalling can be nearly transparent. With languages such as C and C++,
marshalling isn't transparent and may not be available as an option.
While integers and strings don't normally present much of a problem, pointers
and other numerical value data types can cause significant problems. Make sure
you understand the technical side of your processor by the checking the specifications.
3. Obtain 64-bit Runtime Support
Make sure you consider any 64-bit runtime support required for your application.
For example, Microsoft provides AMD-specific support as part of their 64-bit
operating systems. While it's possible to use 32-bit libraries, it generally
isn't possible to use 32-bit runtime support. For most operating systems, this
means having 64-bit versions of all operating system libraries (DLLs) available,
as well as 64-bit drivers.
4. Purchase a 64-bit Test Suite
Even though it might seem that a 32-bit test suite will perform the required
testing tasks, it won't consider issues that arise out of 64-bit numbers. In
addition, you won't find problems with 64-bit pointers, misalignments in arrays,
and many other size-driven considerations. Make sure you check Develop with
AMD for additional help and support.
5. Keep Your Development and Test Machines Separate
It often happens that an application that runs fine on the development machine
won't run at all on a test machine. The development machine becomes "dirty"
as you try various workarounds for porting issues. The test machine is clean
because it contains only the 64-bit elements that the user's Athlon or Opteron
machine will actually have available. In addition, while it's a nuisance to
wipe out your development machine and perform a clean install, wiping out the
test machine isn't a problem at all. You can maintain the clean state of the
test machine by periodically wiping the hard drive and installing a fresh copy
of the operating system and support files that your application requires.
6. Consider Remote Debugging
A common problem for developers working with 64-bit applications is trying to
figure out a way to debug it. Debuggers normally slow things down considerably.
At some point, you're no longer debugging the application; you're waiting for
the computer to do anything at all! Using remote debugging techniques on a high
speed LAN usually speeds things up considerably and makes the debugging experience
better. With AMD processors, you may not have this problem. Their 64-bit debuggers
for Visual Studio and WinDBG specifically can run locally whether debugging
32-bit on 64-bit or 64-bit on 64-bit. There is no slowdown because there is
no emulation layer.
7. Verify Compiler Switches
One of the most common errors that developers make when compiling 64-bit applications
is to use the same compiler switches they've always used. Most compilers require
that you use different switches for a 64-bit build than a 32-bit build. Make
sure you set the compiler switches for the AMD processor of your choice. There
are several to choose from. This
article should help you make up your mind.
8. Perform a 64-bit Build
Some developers get so used to turning every possible warning off to concentrate
on catastrophic errors that they forget these warnings exist. One way to obtain
a list of potential problems with your application is to perform a 64-bit build
of your 32-bit application with all of the warnings turned on. What you'll receive
is a list of every possible problem that could occur with your application.
Even though this list will contain a number of false positives and even a few
issues that you might not wish to pursue, you'll still receive the benefit of
a good look at your application code from the compiler. Because AMD processors
provide full 32-bit support, you'll never run into insurmountable problems as
you might with other processors.
9. Filter Warnings and Errors to Build a Conversion Plan
No matter how you generate a list of warnings and errors about your application
(such as using the compiler or third-party code checking products), you need
to filter the result. First, you need to remove duplicates from the list so
you can concentrate on the issues, rather than become distracted by the vast
number of duplications you'll receive. Second, you need to remove entries that
are non-issues from the list. Use the result to create a conversion plan based
on your existing 32-bit code.
10. Check Dynamic Library Loading Requirements
Some 32-bit dynamic libraries won't load properly in an AMD 64-bit environment.
Many applications had the same problem when moving from the older 16-bit to
the 32-bit environment.
11. Determine Backwards Compatibility Requirements
If you need to continue building both 32-bit and 64-bit versions of your application,
make sure you create an environment in which both applications will compile
using a single code base. You don't want to code everything twice. In C/C++,
using "sizeof()" can become your best friend in this situation with
your second best friend being the template for C++ coding.
Fair:
void * ArrayofPointers [527];
#ifdef SIXTY_FOUR_BIT
// each pointer is 8 bytes of memory
memset (ArrayofPointers, 0, 527*8);
#else
// each pointer is 4 bytes of memory
memset (ArrayofPointers, 0, 527*4);
#endif
Good:
void * ArrayofPointers [527];
memset (ArrayofPointers, 0, 527*sizeof(void*));
Even Better:
void * ArrayofPointers [527];
memset (ArrayofPointers, 0, sizeof(ArrayofPointers));
Remember too that AMD processors make it easier to maintain backward compatibility
by providing full 32-bit support.
12. Consider the Effects of 32-bit and 64-bit Support Requirements
Many companies plunge ahead with program development for AMD 64-bit computers
without considering how a 64-bit application affects support. Make sure you
create an environment in which every part of the 64-bit application has a Universally
Unique Identifier (UUID) or something in the filename, file properties, or something
of that nature, so you can identify the file as a 64-bit file. Otherwise, users
will certainly try to run a 64-bit DLL with their 32-bit application (and vice
versa).
13. Consider the Effects of Multi-Platform Requirements
Multiple platforms need not complicate your 64-bit development endeavors. Start
by assuming that you'll need to use conditional compilation to create multiple
versions of the application. Make sure that each compiler provides the required
support for AMD 64-bit processors. If you use a cross-compiler, make sure the
output works well with each target platform. Actually, multiple platforms can
be helpful. Performing a 64-bit compile on each platform can help you obtain
a better list of potential problems since each platform will likely show different
64-bit flaws. As a result, you can actually produce an application with fewer
flaws in less time when working on multiple platforms.
14. List Data Type Differences and Fixes
The 64-bit environment will almost certainly include new data types and may
deprecate existing data types. Make sure you consider these differences as part
of your plan to upgrade applications to AMD 64-bit processors, and include them
in the list of things to check.
15. Consider Potential Integer Problems
When moving to 64-bit integers, like the ones in AMD Opteron and Athlon processors,
the pointer types and "size_t" change size. If you don't take this
issue into consideration, you might run into an assortment of range checking,
bounds checking, and security issues. In some cases, the code might compile
fine, but fail to run at all. If you want to use 64-bit integers used by you
have to introduce the 64-bit types (e.g., __int64) into your code explicitly.
These types are also supported in the 32-bit compiler for backwards compatibility,
but of course the object code is not as efficient. Instead, you will want to
use the compatibility data types like LONG_PTR to write code that will correctly
compile in either environment. And if you need to target multiple compilers
that have different conventions, use typedefs.
16. Check Your Structures
Data structures will most likely suffer during the move to AMD 64-bit processors.
The problem is that 64-bit numbers take more space, so the natural boundaries
for data structure elements can change. In some cases, the compiler might add
padding that will cause the data structure to become significantly larger than
normal. The differences in size, boundaries, and element locations can combine
to create unusable code, especially when you use the same code base for both
32-bit and 64-bit applications.
17. Revert Arrays as Necessary
Many applications depend on arrays of a certain size with a set spacing for
data elements. Code that depends on the sizes of structures, class or other
data types in memory is a bad programming practice that will be exposed when
you try to port. You might run into a situation where existing code uses the
wrong element spacing and ends up doing things like accessing non-existent memory.
However, you don't need to hard code data sizes because the structure works
better if you use "sizeof()" as the solution.
18. Upgrade Operating System Calls
Most 64-bit operating systems include both 32-bit and 64-bit calls. The reason
is simple; these operating systems have to provide backward compatibility for
existing applications. In Windows, all of the 32-bit system calls and 64-bit
system calls are source-code compatible, provided you use the proper data types
such as LONG_PTR. If you want your Opteron or Athlon application to work in
the 64-bit environment, you must upgrade the operating system calls to use the
new versions.
19. Avoid Unsupported Coding Methods
Traditionally, when a bug showed up in an operating system, device driver, application,
or other software, many developers relied on coding methods not fully supported
by the vendors to overcome flaws in the 32-bit environment. Unfortunately, these
unsupported methods usually lead to trouble when making the move to an AMD 64-bit
environment because the vendor may not recognize the technique and the fix no
longer works. The operating system vendor may take the opportunity to clean
up undocumented behaviors and the differences in data type and size will most
certainly affect your workarounds.
20. Perform Code Base Conversions When Necessary
It's always best if you can maintain a single code base for the various operating
systems and platforms you support with your application; separate code bases
should be the rare exception. However, in some cases, you'll need to have separate
32-bit and 64-bit code bases because supporting a single code base proves impossible,
such as in Assembly language.
21. Use a Version Control System
Version control systems help you manage code updates in a team scenario and
many developers rely on them even when working outside of the team environment.
The need for a version control system is even greater than before when you consider
the vast number of changes you'll make to your application when moving it to
an AMD 64-bit platform.
22. Validate Application Security
Larger variables, increased variable ranges, differences in data types, and
other 64-bit issues will continue to open up new security concerns, but introducing
larger data types should make it easier to write more secure code. Make sure
you throttle variables as needed to match the actual application requirements.
Remember, you don't always need to use the full range of a 64-bit variable.
For example 32-bit:
int size = 1000000;
int count = 1000000;
void * p = malloc (size * count); //
overflow!!!
64-bit:
int size = 1000000;
int count = 1000000;
void * p = malloc (size_t(size) * size_t(count)); // ok
Converting from 32-bit to 64-bit is unlikely to introduce any new security holes
in your code, but the first time you compile for 64-bit, the compiler warnings
will probably flag a large number of holes that your code had all along, but
you weren't aware of.
23. Use 64-bit Friendly Packaging Techniques
Keep in mind that the first impression a user gets of your application is the
installation experience. All installers need to be compatible with the 64-bit
OSes so that they can perform tasks such as writing to the registry correctly.
However, the installer can still be a 32-bit program (and probably should be
so that it works on either type of OS). Bottom line: make sure you use 64-bit
friendly installation packages so the first impression is a good one. When working
with Windows, you may want to check out Microsoft's take on the subject. You
can get a good start on the MSDN Web site.
24. Ensure Support Knows it's a 64-bit Application
One of the biggest problems that developers run into after they finish the conversion
is that the support staff has no idea that the company has even produced a 64-bit
application that relies on an AMD Athlon or Opteron processor. Make sure you
provide your support team with a list of specific questions users may ask so
they can obtain the required information from customers as they enjoy their
new, more powerful AMD 64-bit computers running your applications.
Putting It All Together
As you can see, moving an application from 32-bits to 64-bits is no longer a
question of "if" but "when." Hopefully these tips will allow
you to evolve responsibly and avoid duplicating your efforts.
John Paul Mueller is a freelance author and technical editor. He has produced
69 books and over 300 articles with topics ranging from networking to artificial
intelligence and from database management to heads-down programming. Some of
his current books include 'Windows Administration at the Command Line,' 'Web
Development with Microsoft Visual Studio 2005,' and 'The Savvy Guide to Home
Security.' John has provided technical editing services to both Data Based Advisor
and Coast Compute magazines. He's also contributed articles to magazines including
DevSource, InformIT, SQL Server Professional, Visual C++ Developer, Hard Core
Visual Basic, asp.netPRO, Software Test and Performance, and Visual Basic Developer.
You can read John's weekly blog at www.amazon.com/gp/blog/id/AQOA2QP4X1YWP.