如何在x64 C++;应用程序 将32位Windows C++应用程序移植到64位。不幸的是,代码在DWORD值和指针值之间频繁地双向转换

如何在x64 C++;应用程序 将32位Windows C++应用程序移植到64位。不幸的是,代码在DWORD值和指针值之间频繁地双向转换,c++,winapi,64-bit,x86-64,C++,Winapi,64 Bit,X86 64,其中一个想法是在进程启动期间尽早保留第一个4GB的虚拟进程空间,以便所有后续的保留内存调用都来自大于4GB的虚拟地址。这将导致访问冲突错误—从指针到DWORD再到指针的任何不安全转换,并有助于尽早捕获错误 当我查看一个非常简单的一行C++程序的内存映射时,有很多库在底部4GB中加载?有没有办法确保所有库等只加载4GB以上的数据 谢谢最好的解决方案是修复这些强制转换 不管怎样,您都可以不受影响地截断指针(与强制转换为指针_32相同),因为我相信windows无论如何都会支持较低4GB的应用程序。但

其中一个想法是在进程启动期间尽早保留第一个4GB的虚拟进程空间,以便所有后续的保留内存调用都来自大于4GB的虚拟地址。这将导致访问冲突错误—从指针到DWORD再到指针的任何不安全转换,并有助于尽早捕获错误

当我查看一个非常简单的一行C++程序的内存映射时,有很多库在底部4GB中加载?有没有办法确保所有库等只加载4GB以上的数据


谢谢

最好的解决方案是修复这些强制转换

不管怎样,您都可以不受影响地截断指针(与强制转换为指针_32相同),因为我相信windows无论如何都会支持较低4GB的应用程序。但这并不能保证。你最好还是解决这些问题

在代码中搜索“(DWORD)”并修复找到的任何代码。没有更好的解决办法


实际上,您要求的是在32位内存模式下运行64位代码并启用AWE(即失去64位的所有真正优势)。我不认为微软会为这么少的收益而费心提供这个。。。谁能责怪他们呢?

使用
/Wp64
开关编译项目(检测64位可移植性问题)并修复所有警告。

您可以在应用程序中尽早插入对的调用,以便在较低的4GB内存中分配内存。如果使用
MEM_RESERVE
参数,则只分配虚拟内存空间,因此这只会使用非常少量的实际RAM

但是,这只会对从堆中分配的内存有所帮助—程序中的任何静态数据在WinMain()之前都已分配,因此您将无法更改其位置


(顺便说一句,即使您可以在加载主二进制文件之前保留内存,我认为主二进制文件需要加载到特定的地址,除非它是一个构建为独立于位置的可执行文件。)

Bruce Dawson发布了一种保留底层4 GB虚拟机的技术代码:

它使用
VirtualAlloc
保留大部分地址空间(不是实际内存),然后使用
HeapAlloc
跟踪进程堆,并使用
malloc
完成CRT堆。它简单、快速,效果非常好。在我的机器上,它执行大约3.8GB的虚拟分配,实际分配只有1MB


第一次尝试时,我立即发现我正在进行的项目中存在一个长期存在的bug。强烈推荐。

该选项不是声明为“已弃用”吗?仅使用x64编译器编译应该会得到所有警告(比/Wp64更准确,这就是为什么该开关已弃用的原因)。文档中说/Wp64已弃用,它将生成令人讨厌的警告“命令行警告D9035:‘Wp64’已被弃用,并将在将来的版本中删除”警告,但在x64版本中启用它将给您提供有用的警告(关于从较小的整数类型转换指针)我检查了MSDN-它从VS2008开始就被弃用了,我正在使用VS2005,但它还没有被弃用。/Wp64因为工作不太好而被弃用。64位编译器是在编译时查找截断问题的更好选择。要在运行时查找问题,请参阅shoelzer的答案。谢谢。我计划如果可能的话,在一个DllMain中安装VirtualAlloc。问题是MSVC运行时在4GB之前加载。可执行文件的首选地址高于4GB,因此在4GB以上加载就可以了。您可以更改程序(或DLL)的位置静态/全局数据和代码,方法是在链接时设置其首选基址,或使用rebase.exe更改其首选基址。某些滥用延迟加载DLL的行为可能会允许您调用VirtualAlloc()在大多数DLL加载之前。显然,您仍然需要加载Kernel32.DLL。您阅读了问题吗?海报并不是问如何避免超过4GB的地址。(如果是这样,答案将是向链接器传递/largeaddressware=NO。)还有更好的方法来发现指针截断问题,而不是对C样式转换的代码进行grep。早期的VirtualAlloc技术不会阻止所有代码都位于底部4 GB,但函数指针很少被截断,因此这可能无关紧要。此外,ASLR应该将二进制文件放在4 GB行之上,尤其是如果你把它放在额外的熵模式。