我最近的大部分编程都是在使用 C/C++/C#/VB6 的 32 位 Windows 上进行的。最近,我的客户询问我的代码是否可以在 64 位 Windows 上运行。
我想知道我可能使用的哪些遗留功能会在 64 位 Windows 上中断?我需要考虑和担心哪些现实问题?
显然,我将在 64 位操作系统上测试我的代码,但我想知道要查找哪些常见问题。我更关心现有的二进制文件,但我愿意就重新编译时(在可能的情况下)时要担心的问题发表评论。
编辑:这是一个很好的 64 位移植错误列表。
我最近的大部分编程都是在使用 C/C++/C#/VB6 的 32 位 Windows 上进行的。最近,我的客户询问我的代码是否可以在 64 位 Windows 上运行。
我想知道我可能使用的哪些遗留功能会在 64 位 Windows 上中断?我需要考虑和担心哪些现实问题?
显然,我将在 64 位操作系统上测试我的代码,但我想知道要查找哪些常见问题。我更关心现有的二进制文件,但我愿意就重新编译时(在可能的情况下)时要担心的问题发表评论。
编辑:这是一个很好的 64 位移植错误列表。
就我而言,将 C/C++ 代码移植到 64 位 Windows 的最重要的事情是在启用分配(注册表值)的情况下测试您的应用程序,MEM_TOP_DOWN
AllocationPreference
如4-Gigabyte Tuning中所述:
要强制分配在较低地址之前从较高地址分配以进行测试,请
MEM_TOP_DOWN
在调用时指定VirtualAlloc
或将以下注册表值设置为 0x100000:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Memory Management\AllocationPreference
这什么时候有关系?
/LARGEADDRESSAWARE
如果您有使用MSVC 链接器选项构建的现有 32 位 EXE (或IMAGE_FILE_LARGE_ADDRESS_AWARE
通过其他方式在其 PE 标头中设置标志,例如editbin.exe
),那么它们将获得完整的 4 GB 64 位虚拟地址空间Windows,您必须使用AllocationPreference
注册表值集对其进行测试。AllocationPreference
注册表值集对其进行测试。AllocationPreference
注册表值集对其进行测试。如果您的 C/C++ 应用程序属于这三个类别之一并且您不使用MEM_TOP_DOWN
分配进行测试,则测试不太可能在您的代码中捕获任何指针截断/签名错误。
第二个最重要的事情是,如果您使用 MSVC 并且正在为 64 位重新编译 C/C++ 代码,则为您的64 位构建使用/Wp64
编译器选项:
reinterpret_cast
使用 C 样式转换),以及其他一些 64 位移植问题。/Wp64
编译,不如使用针对 64 位平台的编译器,但仅此一项就不会在编译时捕获指针截断/扩展问题。使用面向 64 位的编译器并/Wp64
为 64 位构建启用编译器选项将在编译时捕获许多指针截断/扩展问题,从长远来看,这将节省您的时间。/Wp64
选项已被弃用。我可以看到为什么该选项在 32 位构建中被弃用(它是一个邪恶的 hack,需要注释您的许多 typedef),但不幸的是,它也被 64 位构建弃用(它实际上很有用)。文章:
64 位、Wp64、Visual Studio 2008、Viva64 和所有其他...
将 C 和 C++ 代码迁移到 64 位 Windows 期间的陷阱检测
和
Viva64 工具 - 用于检查 64 位程序:
如果您谈论的是 32 位程序,那么您几乎无需担心,因为 Windows 64 将在仿真下将它们作为 32 位运行。未来 Windows 版本(例如 Windows 7)的任何问题都可能是不兼容问题,而不是 64 位操作系统的问题。
但是,如果您的托管代码是为“任何 CPU”目标平台编译的,并且您调用非托管代码(例如 PInvoke),或者依赖于其他程序集,那么需要注意一些事项。Scott Hanselman 关于 x86/x64 CLR 的帖子涵盖了这一点,并且很好地解释了 Win32/64 上的 CLR。
在开发 64 位本机程序时,64 位 Windows 编程指南是一个很好的指南。它主要归结为指针和数据类型的大小:)
32 位程序可以在 64 位窗口上正常运行。当然,只要您不进行任何设备驱动程序类型的开发。
如果您第一次将软件编译为 64 位软件,则需要注意以下事项:
如果您出于任何原因进行 DLL 注入,您将遇到麻烦。
从 C/C++ 的角度来看......
一件显而易见的事情是 int 的大小将变为 8 个字节而不是 4 个字节。如果您的任何代码依赖于它,您可能会得到意想不到的结果。结构和变量对齐可能会发生变化。您可以使用#pragma pack 克服它,但我对对齐和打包不是很流利。
如果您使用其中包含整数的任何联合,则行为可能会改变。
如果您使用任何位域结构,基于整数的额外 32 位可能会导致混淆。符号位不会是您认为的位置。
如果您编写任何十六进制常量并期望符号变为负数,您可能会遇到问题。示例 0x8000000 是作为日志的负数,或 32 位整数。0x80000000 作为 64 位平台上的整数是一个正数。要直接设置符号位,您必须使用 0x80000000 00000000 (嵌入空间仅供阅读)
我也希望 size__t 能够适当增长。如果您基于 MAX_INT 进行任何分配,它们会更大。
为了避免这些类型的大小异常,我通常坚持使用 long 而不是 int。
32 位仿真真的是防弹的吗?我已经看到注册表的布局略有不同。我只是想知道哪些典型的事情不起作用......
此外,C:\windows\SYSTEM32 目录只能包含 64 位 DLL。如果你有一个 32 位的 DLL,你需要把它放在 C:\windows\syswow64\