English 中文(简体)
作为一名程序员,当迁移到64位Windows时,我需要担心什么?
原标题:
  • 时间:2009-02-13 01:03:43
  •  标签:

我最近大部分编程都是在32位Windows上使用C/C++/C#/VB6。最近,我的客户都在询问我的代码是否能在64位Windows上运行。

我在想,我可能正在使用哪些遗留特性会在64位Windows上出故障?我需要考虑和担心哪些真实世界中的问题?

显然,我将在64位操作系统上测试我的代码,但我想知道要注意哪些常见问题。我更关心现有的二进制文件,但我也欢迎对重新编译时可能出现的问题进行评论。

编辑:这是一个不错的清单,其中包含了64位移植错误的示例。

最佳回答

文章

在64位平台上移植C++代码的20个问题

64位程序开发中被遗忘的问题

64位、Wp64、Visual Studio 2008、Viva64和所有其他...

将 C 和 C++ 代码迁移到 64 位 Windows 期间的陷阱检测

AMD64(EM64T)架构

"and" translated into Chinese is "和" (hé).

Viva64工具-用于检查64位程序:

Viva64是什么,面向谁?

问题回答

就我而言,将C/C++代码移植到64位Windows的最重要的事情就是使用启用了MEM_TOP_DOWN分配(AllocationPreference注册表值)的应用程序进行测试,如4-Gigabyte Tuning中所述:

为了进行测试目的,强制分配在从较高地址到较低地址分配时,请在调用VirtualAlloc时指定MEM_TOP_DOWN或将以下注册表值设置为0x100000:

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

这什么时候重要?

  • 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.

如果你的C/C++应用程序属于以下三种情况之一,而你没有使用 MEM_TOP_DOWN 分配进行测试,则测试极有可能无法捕获代码中的任何指针截断/有符号错误。

如果您使用MSVC并正在重新编译C/C++代码以用于64位,第二个最重要的事情是为64位构建使用/Wp64编译器选项

  • 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).

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.

顺便提一下, Hanselman 最近写了博客讨论了这个主题。

如果你在谈论32位程序,那么你实际上不必担心太多,因为Windows 64位将通过仿真运行它们作为32位。未来Windows版本(如Windows 7)出现的任何问题可能是不兼容性问题而不是64位操作系统的问题。

但是,如果您的托管代码编译为“任何 CPU”目标平台,并且您调用未管理的代码(例如PInvoke),或者依赖于其他程序集,则需要注意一些事情。Scott Hanselman的帖子关于x86 / x64 CLR涵盖了这一点,并且是Win32 / 64上CLR的很好的解释。

当开发64位本地程序时,64位Windows编程指南是一个不错的指南。它主要涉及指针和数据类型的大小 :)

32位程序可以正常运行在64位的Windows上。当然,只要您不进行任何设备驱动程序的开发。

如果您第一次将软件编译为64位软件,则需要注意以下事项:

  • 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.

如果你因任何原因做DLL注入,你会遇到麻烦。

从C/C++角度来看...

一件明显的事情是,int的大小将从4字节变为8字节。如果您的任何代码依赖于它,您可能会得到意想不到的结果。 结构和变量的对齐可能会发生变化。您可以通过#pragma pack来克服它,但我在对齐和打包方面并不很熟练。

如果您将int与任何联合使用,行为可能会改变。

如果您正在使用基于int的任何位域结构,则额外的32位可能会引起混淆。符号位可能不在您原来认为的位置上。

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)

我也期望 size__t 适当增长。 如果您基于 MAX_INT 进行任何分配,则它们将更大。

为了避免这类大小异动,我通常使用 longs 而不是 ints。

32位仿真真的是防弹的吗?我已经看到注册表布局有一点不同。我只是想知道哪些典型的事情不能工作...

此外,C:windowsSYSTEM32目录只能包含64位DLL。如果您有一个32位DLL,则需要将其放在C:windowssyswow64中。





相关问题
热门标签