【问题标题】:How can I enable my 32-bit Delphi application to use 4gb of memory on 64-bit windows (via Wow64.exe)?如何让我的 32 位 Delphi 应用程序在 64 位窗口上使用 4GB 内存(通过 Wow64.exe)?
【发布时间】:2010-12-23 09:21:02
【问题描述】:

据此MSDN page

WOW64 使 32 位应用程序能够 利用 64 位内核。 因此,32 位应用程序可以使用 更多的内核句柄和 窗把手。但是,32 位 应用程序可能无法创建 WOW64 下的线程数与它们一样多 在基于 x86 的本机运行时可以 系统,因为 WOW64 分配了一个 额外的 64 位堆栈(通常为 512 KB) 为每个线程。此外,一些 保留的地址空间量 对于 WOW64 本身和数据 它使用的结构。数量 保留取决于处理器; Intel Itanium 保留了更多内容 比在 x64 处理器上。

如果应用程序有 IMAGE_FILE_LARGE_ADDRESS_AWARE 标志 在图像头中设置,每个 32 位 应用程序接收 4 GB 的虚拟 WOW64中的地址空间 环境。如果 IMAGE_FILE_LARGE_ADDRESS_AWARE 标志是 未设置,每个 32 位应用程序 接收 2 GB 的虚拟地址空间 在 WOW64 环境中。

如何在我的 Delphi 2007 应用程序中有效地设置 IMAGE_FILE_LARGE_ADDRESS_AWARE 标志,以便让我的 32 位应用程序 Wow64 感知并寻址高达 4GB 的内存?

【问题讨论】:

    标签: delphi 64-bit 32-bit


    【解决方案1】:

    请参阅此 CodeCentral 文章:Using more than 3 GB memory in a 32 bit Delphi program

    在现代 Delphi 版本中,只需将编译器指令添加到 dpr: {$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}

    【讨论】:

    • 我不确定这会对任何人都有帮助,但是应该在使用 WinApi.Windows 之后使用此指令;因为某些 Delphi 版本需要它才能工作。
    【解决方案2】:

    使用链接器指令 $SetPEFlags:

    {$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}
    

    IMAGE_FILE_LARGE_ADDRESS_AWARE 常量在 Windows.pas 中定义。不过,我不记得是哪个 Delphi 版本最先包含它的。

    在 Delphi 2007 中,您会发现 SetPEFlags 记录在 "PE (portable executable) header flags (Delphi)"

    一些有用的IMAGE_FILE_HEADER标志

    • {$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE} //$0020

      应用程序可以处理大于 2 GB 的地址。

    • {$SetPEFlags IMAGE_FILE_NET_RUN_FROM_SWAP} //$0800

      如果图像在网络上,请将其复制到交换文件并从交换文件中运行。

    • {$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP} //$0400

      如果图像位于可移动媒体上,请将其复制到交换文件并从交换文件运行。

    一些IMAGE_FILE_HEADER标志

    • {$SetPEOptFlags IMAGE_DLLCHARACTERISTICS_NX_COMPAT} //$0100

      图像与数据执行保护 (DEP) 兼容。

    • {$SetPEOptFlags IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE} //$0040

      DLL 可以在加载时重新定位。 (又名 ASLR - 地址空间布局随机化)

    • {$SetPEOptFlags IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE} //$8000

      The image is terminal server aware.

    【讨论】:

      【解决方案3】:

      请注意,编译器和 RTL 中有一些假设,即被解释为有符号 32 位整数的指针永远不会是负数。例如,编译器不允许创建大小超过 2GB 的数据结构,并且 RTL 中的某些边界检查假定例如Index + Count < 0 表示加法溢出,其中Index 可能是字节数组的索引。内存管理器中可能会出现其他问题。

      测试良好,风险自负。

      【讨论】:

      • 是否有可能修复 RTL/VCL 中的此类问题(如果存在)? :)
      • 为什么指针应该被解释为有符号的 32 位整数?对我来说,这听起来像是 Embarcadero 应该修复的有缺陷的设计,特别是因为您似乎并不急于发布 64 位版本的 Delphi。
      • @Jan Goyvaerts - 像我描述的那样简单、轻松、高效地检测溢出。并且围绕 64 位等的营销和产品决策与我在这里发布的具体技术警告完全无关。
      【解决方案4】:

      如果您这样做,请确保使用 FastMM,因为它支持 > 2GB 的指针。正如 Barry Kelly 已经描述的那样,早期的 Delphi 内存管理器无法正常工作。

      【讨论】:

      • 链接:FastMM4 支持 Delphi 4 及更高版本,FastMM5 支持 Delphi XE3 及更高版本。
      猜你喜欢
      • 1970-01-01
      • 2011-08-20
      • 1970-01-01
      • 2013-08-19
      • 1970-01-01
      • 2017-05-13
      • 2012-08-11
      相关资源
      最近更新 更多