我最近的编程大部分是在32位Windows上使用C / C ++ / C#/ VB6。 最近,我的客户询问我的代码是否可以在64位Windows上运行。
我想知道我可能使用的旧function将在64位Windows上打破吗? 我需要考虑和担心什么是现实世界的问题?
很显然,我将在64位操作系统上testing我的代码,但我想知道需要寻找哪些常见问题。 我更关心现有的二进制文件,但是我很乐意在重新编译时(如果可能的话)担心什么。
编辑:这是一个不错的64位移植bug的列表 。
文章:
在64位平台上移植20个C ++代码的问题
被遗忘的64位程序开发问题
64位,Wp64,Visual Studio 2008,Viva64和所有其他…
将C和C ++代码迁移到64位Windows时进行陷阱检测
AMD64(EM64T)架构
和
Viva64工具 – 用于检查64位程序:
Viva64:这是什么意思?
就我而言,将C / C ++代码移植到64位Windows最重要的一件事就是在启用MEM_TOP_DOWN
分配( AllocationPreference
注册表值)的情况下测试应用程序,如4千兆字节调整中所述 :
为了强制分配从较低地址之前的较高地址分配用于测试目的,
MEM_TOP_DOWN
在调用VirtualAlloc
时指定MEM_TOP_DOWN
或将以下注册表值设置为0x100000:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Memory Management\AllocationPreference
这是什么时候?
/LARGEADDRESSAWARE
MSVC链接器选项构建的现有32位EXE(或通过其他方式(例如editbin.exe
)在其PE标头中设置了IMAGE_FILE_LARGE_ADDRESS_AWARE
标志),则它们将获得完整的4 GB虚拟地址空间在64位Windows中,并且您必须使用AllocationPreference
注册表值集来测试它们。 AllocationPreference
注册表值设置测试它们。 AllocationPreference
注册表值进行测试。 如果您的C / C ++应用程序属于这三个类别之一,并且您不使用MEM_TOP_DOWN
分配进行测试,则测试不太可能捕获代码中的任何指针截断/签名错误。
第二个最重要的事情是,如果你使用MSVC并且你正在重新编译64位的C / C ++代码, /Wp64
你的64位版本使用/Wp64
编译器选项 :
reinterpret_cast
或C风格转换时),以及其他一些64位移植问题。 /Wp64
进行编译,而应该使用一个针对64位平台的编译器,但在编译时单独不会捕获指针截断/扩展问题。 使用以64位为目标的编译器并为64位版本启用/Wp64
编译器选项将在编译时捕获许多指针截断/扩展问题,这将为您节省时间。 /Wp64
选项已被弃用。 我可以看到为什么这个选项在32位构建中被弃用(这是一个邪恶的黑客,它需要注释你的许多类型定义),但不幸的是,它也被弃用于64位构建(实际上是有用的)。 如果您有100%“类型安全的托管代码”,迁移.NET代码可能会更容易。 您可以将其复制到64位平台,并在64位CLR下成功运行。 请查看此MSDN链接将 32位托管代码迁移到64位。
顺便说一下,hanselman最近在这个话题上做了博客 。
如果你正在谈论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来克服它,但是我在对齐和打包方面不太流利。
如果您使用任何带有ints的工会,行为可能会改变。
如果您使用任何位域结构,则基于整数,额外的32位可能会导致混淆。 标志位不会是你以为是的地方。
如果你编码任何十六进制常量,并期望迹象消极,你可能有问题。 示例0x8000000是作为日志或32位整数的负数。 作为64位平台上的整数0x80000000是一个正数。 直接设置符号位,你将不得不使用0x80000000 00000000(嵌入式空间仅用于可读性)
我也希望大小适当增长。 如果你正在做任何基于MAX_INT的分配,它们将会大得多。
为了避免这种类型的大小异常,我通常坚持多头,而不是整数。
32位仿真真的是防弹吗? 我已经看到注册表有一点不同了。 我只是想知道什么典型的东西不工作…
另外,C:\ windows \ SYSTEM32目录只能包含64位DLL。 如果你有一个32位的DLL,你需要把它放在C:\ windows \ syswow64 \