作为程序员,在迁移到64位窗口时需要担心什么?

时间:2009-02-13 01:03:44

标签: windows 32bit-64bit

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

我想知道我可能会在64位Windows上使用哪些遗留功能?我需要考虑和担心的一些现实问题是什么?

显然,我将在64位操作系统上测试我的代码,但我想知道要寻找的常见问题。我更关心现有的二进制文件,但我很乐意在重新编译时(如果可能的话)担心会有什么问题。

编辑:这是64位移植错误的nice list

8 个答案:

答案 0 :(得分:22)

就我而言,将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

什么时候重要?

  • 如果您现有的32位EXE是使用/LARGEADDRESSAWARE MSVC链接器选项构建的(或者通过其他方式在其PE头中设置了IMAGE_FILE_LARGE_ADDRESS_AWARE标志,例如{{1}然后,他们在64位Windows中获得了完整的4 GB虚拟地址空间,您必须使用editbin.exe注册表值设置它们进行测试。
  • 如果您有可由大地址识别EXE加载的现有32位DLL,则必须使用AllocationPreference注册表值设置来测试它们。
  • 如果将C / C ++代码重新编译为64位EXE或DLL,则必须使用AllocationPreference注册表值进行测试。

如果您的C / C ++应用程序属于这三个类别中的一个并且您没有使用AllocationPreference分配进行测试,则测试不太可能捕获代码中的任何指针截断/签名错误。

第二个最重要的事情,如果您使用MSVC并且要重新编译64位的C / C ++代码,那么使用 64位的MEM_TOP_DOWN编译器选项 build

  • 这将导致编译器为截断指针或将较小的整数类型扩展为指针的类型转换发出警告(即使使用/Wp64或C样式转换),以及其他一些64位移植问题。
  • 是的,documentation表示不应使用reinterpret_cast进行编译,而应使用针对64位平台的编译器,但仅在编译时不会捕获指针截断/扩展问题。使用针对64位的编译器为64位构建启用/Wp64编译器选项将在编译时捕获许多指针截断/扩展问题,这将节省您的时间从长远来看。
  • 不幸的是,对于MSVC 2008,这也会为每个翻译单元产生一个“命令行警告”,表示不推荐使用/Wp64选项。我可以看到为什么该选项不适用于32位版本(这是一个需要注释你的许多typedef的邪恶黑客),但不幸的是它也被弃用于64位版本(它实际上很有用)。

答案 1 :(得分:15)

答案 2 :(得分:5)

如果您拥有100%“类型安全的托管代码”,那么迁移.NET代码可能会更容易。 您只需将其复制到64位平台并在64位CLR下成功运行即可。 关于将32位托管代码迁移到64位,请检查此MSDN link

Btw,hanselman blogged最近关于这个话题。

答案 3 :(得分:3)

如果您正在谈论32位程序,那么几乎没有什么可担心的,因为Windows 64将在模拟下以32位运行它们。未来Windows版本(例如Windows 7)的任何问题都可能是不兼容的,而不是64位操作系统的问题。

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

在开发64位本机程序时,Programming Guide for 64-bit Windows是一个很好的指南。它主要归结为指针和数据类型的大小:)

答案 4 :(得分:2)

32位程序将在64位窗口上正常运行。只要你没有做任何设备驱动程序的开发当然。

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

  • 指针是64位宽,而int是32位。不要将指针存储在整数中,代码就会中断。
  • 64位进程需要64位DLL。如果您依赖第三方DLL,请确保它们也以64位提供。如果需要在32位进程和64位进程之间进行通信,则需要在Windows上使用许多不同的IPC方法。直接调用函数是不可能的。
  • 64位Windows上的系统目录与32位Windows上的系统目录不同。如果您有一些硬编码路径,则可能需要再次检查它们。

答案 5 :(得分:1)

如果因任何原因进行DLL注入,则会遇到麻烦。

答案 6 :(得分:0)

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

一个显而易见的事情是int的大小将变为8个字节而不是4个字节。如果您的任何代码依赖于您,您可能会得到意想不到的结果。结构和变量对齐可能会发生变化。您可以使用#pragma pack克服它,但我对齐和包装不是很流畅。

如果你使用任何包含int的联合,行为可能会改变。

如果使用任何位域结构,基于整数,额外的32位可能会引起混淆。符号位不会是您认为的位置。

如果您编码任何十六进制常量并且预期符号会变为负数,则可能会出现问题。例 0x8000000是一个负数作为日志,或32位整数。在64位平台上作为整数的0x80000000是正数。直接设置符号位,你必须使用0x80000000 00000000(嵌入空间只是为了可读性)

此外,我希望size__t适当增长。如果您根据MAX_INT进行任何分配,它们会更大。

为了避免这些类型的异常,我通常坚持使用long而不是整数。

答案 7 :(得分:0)

32位仿真真的是防弹吗?我已经看到注册表的布局略有不同。我只是想知道什么是典型的东西不起作用......

此外,C:\ windows \ SYSTEM32目录只能包含64位DLL。如果您有32位DLL,则需要将其放在C:\ windows \ syswow64 \