为什么在64位Windows中运行时有2 GB的内存限制?

32
我是一个参与开发 Delphi 应用程序的团队成员。该应用程序的内存需求很大,通常情况下为 500MB,但有时会出现内存不足异常。在这些情况下分配的内存通常在 1000-1700MB 之间。
我们当然希望使用 64 位编译器,但现在不可能实现(即使实现了也必须转换为 Unicode,但这又是另一回事...)。
我的问题是,为什么在 64 位环境中运行时每个进程有2GB的内存限制?指针是32位的,因此我认为4GB应该是正确的限制。 我使用的是 Delphi 2007。
编辑: 所以如果我在 Delphi 中设置 IMAGE_FILE_LARGE_ADDRESS_AWARE 标志,可以用以下方法:
{$SetPeFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}

如果在Windows Server 2003 x64上运行生成的Exe文件,该应用程序能够访问4 GB吗?

  • 我应该在boot.ini中设置/3GB开关吗?
  • 我们尝试过在32位Windows Server 2003上这样做,但似乎会限制Windows资源。日志中会有更多的"GDIError内存不足"异常。但是在64位操作系统上运行时,这可能会消失吗?

boot.ini中的3GB开关仅适用于32位Windows,并且需要启用LARGEADDRESSAWARE才能工作。请注意,它会缩小32位系统上Windows本身可用的空间。例如,请参见此处http://blogs.technet.com/markrussinovich/archive/2009/03/26/3211216.aspx,或阅读Russinovoch和Solomon的优秀著作“Windwos Internals”。 - user160694
4个回答

32
如果你使用 /LARGEADDRESSAWARE 标志编译 Delphi 应用程序,它将能够在 64 位操作系统中寻址整个 4GB。否则,在 WOW32 中运行时,操作系统会假定该应用程序希望获得与在 32 位操作系统上相同的环境,这意味着在 4GB 地址空间中,2GB 用于操作系统,2GB 分配给应用程序。

5
这仅适用于32位系统。在3GB指针和4GB指针之间没有二进制差别,因此任何能处理3GB的应用程序都可以处理4GB。在64位系统上,/LARGEADDRESSAWARE对完整的4GB很好,而无需进行任何启动修改。唯一需要使用/3GB的情况是您想在32位系统中使用更多地址空间。您提供的文章已经过时约十年,只涉及32位系统。PAE是一个完全不同的系统。 - Puppy
2
@Deltics - LARGEADDRESSAWARE不仅适用于3GB,那是绝对错误的。http://msdn.microsoft.com/en-us/library/wz223b1z%28VS.80%29.aspx。这是一种指示应用程序可以处理**任何**超过2GB的地址的方法。如果您想在64位操作系统上使用32位应用程序并且它可以处理的话,并且需要完整的4GB地址空间,则可以使用LARGEADDRESSAWARE开关。我不确定您为什么认为这是不正确的。 - Thomas
1
答案明确指出了64位操作系统,那有什么问题呢? - Mark Ransom
1
@Deltics - 此外,您提供的文章中的第一段完全支持我的观点,即对于32位操作系统而言,4GB地址空间的使用方式为2GB用于操作系统,另外2GB用于应用程序。这是默认行为。/3GB是一个功能,您可以手动启用它以更改这种动态,从而分配多达3GB给应用程序如果它被设计为处理额外的寻址。 - Thomas
1
@所有人:没问题,除了第二个句子以连词开头让我有些困惑之外。我的错误。我已经删除了冒犯性的评论,不是为了挽回面子,而是为了避免在任何人的脑海中植入怀疑的种子。 - Deltics
显示剩余2条评论

15

在 Delphi 中设置 PE 可执行文件中 LARGEADDRESSAWARE 标志的语法为:

{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}

将其放入您的 .dpr 文件中。


6

4
Windows无法知晓Delphi在内存地址上使用的是带符号还是无符号算术运算,因此除非您明确声明,否则Windows必须假设最高位无法使用。 - Mark Ransom
@Mark:那个,啊,完全不是真的。正如上面所述,设置引导标志将允许Delphi处理超过2GB的内存。 - BlueRaja - Danny Pflughoeft
1
@BlueRaja,“设置启动标志”=“明确声明否定”。 - Mark Ransom
@Mark:我的意思是操作系统中的启动标志。这与Delphi或有符号算术没有任何关系(指针算术无论有符号还是无符号都是相同的!) - BlueRaja - Danny Pflughoeft
1
@BlueRaja:你错了。http://blogs.msdn.com/oldnewthing/archive/2004/08/12/213468.aspx - Alex

2
只要您选择使用高位设置的32位指针(通过包含 PE标志),就没有2GB限制。
直接观察
var
   p: Pointer;
   n: Int64;
begin
   p := Pointer($D0000000); //Above the 2GB line; and the 3GB line!

   p := VirtualAlloc(p, 1024, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
   if p = nil then
      RaiseLastWin32Error;

   n := Cardinal(p);
   ShowMessage(IntToHex(n, 16));
end;

结论

在64位Windows上,只要你能处理$7FFFFFFF以上的指针,就没有2GB的限制。

注意:任何代码都被释放到公共领域,不需要归属。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接