views:

1115

answers:

8

Most of my recent programming has been on 32-bit Windows using C/C++/C#/VB6 . Lately, my customer are asking if my code will run on 64-bit Windows.

I'm wondering what legacy features I might be using that will break on 64-bit Windows? What are some real-world issues I need to think about and worry about?

Obviously, I will test my code on the 64-bit OS, but I'd like to know what common issues to look for. I more concerned with the existing binaries, but I am open to comments about what to worry about when recompiling (where possible).

+4  A: 

It might be easier to migrate .Net code if you have 100% "type safe managed code". You can just copy it to the 64-bit platform and run it successfully under the 64-bit CLR. Check this MSDN link on migrating 32-bit Managed code to 64-bit.

Btw, hanselman blogged about the topic recently.

Gulzar
That is a good tip, for the .NET code.
jm
+3  A: 

If you are talking about 32-bit programs then you have practically nothing to worry about since Windows 64 will run them under emulation as 32-bit. Any problems with future Windows versions (e.g Windows 7) are likely to be incompatibilities rather than issues with a 64-bit OS.

However if your managed code is compiled for the "Any CPU" target platform and you make calls into unmanaged code (e.g PInvoke), or are dependent on other assemblies then there are some things to be aware of. Scott Hanselman's post about the x86/x64 CLR covers this and is a good explanation of the CLR on Win32/64.

When developing 64-bit native programs then the Programming Guide for 64-bit Windows is a good guide. It largely comes down to pointers and the size of data types :)

Andrew Grant
A: 

From a C/C++ perspective....

One obvious thing is that the size of an int will become 8 bytes instead of 4 bytes. If any of your code is dependent on that you may get unexpected results. Structure and variable alignments may shift. You may be able to overcome it with a #pragma pack, but I am not very fluent in alignments and packing.

If you use any unions with ints in them, the behavior may change.

If you are using any bitfield structures, based on ints the extra 32 bits may cause confusion. The sign bit won't be where you thought it was.

If you code any hex constants and expect signs to go negative, you may have issues. Example 0x8000000 is a negative number as a log, or 32 bit integer. 0x80000000 as an integer on a 64 bit platform is a positive number. to directly set the sign bit you would have to use 0x80000000 00000000 (embedded space for readability only)

Also I expect size__t to grow appropriately. If you are making any allocations based on MAX_INT, they will be much larger.

To avoid these type of size anomalies, I generally stick with longs instead of ints.

Well, you should use something like http://en.wikipedia.org/wiki/Stdint.h to actually specify the bits that you want.
Calyth
Isn't int still 32 bits in Win64?
Peter
int is still 32-bits in Win64 - not so obvious I guess :)
Andrew Grant
@Calyth: A big +1 on the comment about using the appropriate header for standard types.
mghie
I guess your right, int ain't necessarily 8 unless your compiling in 64 bit mode for 64 bit platform. Looks like MSvc 2008 still build 4 byte ints out of the box.
64-bit normally means that pointers are 64 bits, and there has to be some sort of 64-bit integral type. Sometimes int and long will be 32 bits, and long long will be 64. It depends on the implementation. It's usually dangerous to make assumptions on the size of a data type.
David Thornley
on win64, both int and long are still 4 bytes.
David Cournapeau
A: 

32bit programs will run fine on 64 bit windows. As long you are not doing any device driver kind of development of course.

If you compile your software as a 64 bit software the first time, you need to take care of following:

  • a pointer is 64 bit wide, while an int is 32 bit. Don't store pointers in ints, your code will break.
  • 64 bit process need 64 bit DLLs. If you depend on third part DLLs, make sure they are also provided in 64 bit. If you need to communicate between a 32 bit process and a 64 bit process, you will need some of the many different ways of IPC on Windows. Calling functions directly is out of question.
  • The system directories on 64 bit Windows are different than on 32 bit Windows. If you have some hard coded paths, you might need to check them again.
As noted by others, there are lots more things that could be done assuming a certain integer size that would break. I don't think it's right to just brush it off to say as long as you don't do any device driver dev, you'd be ok.
Calyth
I have yet to see a 32 bit app breaking on 64 bit windows - as long as it's not a device driver. They simply do not run on 64 bit Windows.
Casting a pointer to an int has been used on so many projects and arguably bad samples that it's THE common source of 32->64 bit problem. I've yet to see any kind of other legal usage of the constructs of the langauges the OP asked for that are worth mentioning.
While I agree on the need to re-check all hard-coded paths - there shouldn't be any (to system directories) in a properly written Windows application, anyway. There are API functions to get the correct values, and anything else can and will fail in non-English or non-standard OS installations.
mghie
A: 

Is the 32-bit emulation really bullet proof? I have seen that the registry is layed out a little differently. I'm just wondering what typical things don't work...

Also, the C:\windows\SYSTEM32 directory can only contain 64-bit DLLs. If you have a 32-bit DLL, you need to put it in C:\windows\syswow64\

jm
+5  A: 

As far as I'm concerned, the single most important thing about porting C/C++ code to 64-bit Windows is to test your application with MEM_TOP_DOWN allocations enabled (AllocationPreference registry value) as described in 4-Gigabyte Tuning:

To force allocations to allocate from higher addresses before lower addresses for testing purposes, specify MEM_TOP_DOWN when calling VirtualAlloc or set the following registry value to 0x100000:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Memory Management\AllocationPreference

When does this matter?

  • If you have existing 32-bit EXEs that were built with the /LARGEADDRESSAWARE MSVC linker option (or which have the IMAGE_FILE_LARGE_ADDRESS_AWARE flag set in their PE headers through other means, such as editbin.exe), then they get a full 4 GB of virtual address space in 64-bit Windows, and you must test them with the AllocationPreference registry value set.
  • If you have existing 32-bit DLLs that may be loaded by large address aware EXEs, you must test them with the AllocationPreference registry value set.
  • If you recompile your C/C++ code into a 64-bit EXE or DLL, you must test it with the AllocationPreference registry value set.

If your C/C++ application falls into one of these three categories and you don't test with MEM_TOP_DOWN allocations, testing is very unlikely to catch any pointer truncation/signedness bugs in your code.

The second most important thing, if you use MSVC and you are recompiling C/C++ code for 64-bit, is to use the /Wp64 compiler option for your 64-bit build:

  • This will cause the compiler to emit warnings for typecasts that truncate pointers or extend smaller integral types into pointers (even when reinterpret_cast or a C-style cast is used), as well as a few other 64-bit porting issues.
  • Yes, the documentation says that instead of compiling with /Wp64 you should use a compiler that targets a 64-bit platform, but that alone will not catch pointer truncation/extension issues at compile time. Using a compiler that targets 64-bit and enabling the /Wp64 compiler option for the 64-bit build will catch many pointer truncation/extension issues at compile time, and this will save you time in the long run.
  • Unfortunately, with MSVC 2008, this will also produce a "command line warning" for each translation unit saying that the /Wp64 option is deprecated. I can see why the option is deprecated for 32-bit builds (where it is an evil hack that requires annotating many of your typedefs), but it's unfortunate that it is also deprecated for 64-bit builds (where it is actually useful).
bk1e
+1  A: 

If you do DLL injection for any reason you will have trouble.

Joshua