请问 TObject.Create的内部内存分配是基于虚存分配还是物理内存?(100分)

  • 主题发起人 主题发起人 比尔
  • 开始时间 开始时间

比尔

Unregistered / Unconfirmed
GUEST, unregistred user!
我的程序要处理很大的数据量(500M),我设计了一个类把它们全读出来了,在类成员变量指针分配时我都用
VirtualAlloc代替GetMem或New来实现虚存分配,但我的类TMyClass.Create的内存分配是底层做的,
好象仍然是物理/逻辑内存分配(我机器是256M内存,在分配了370M左右时系统仍然报错:
out of memory),我无法改,我该怎么办?谢谢!
 
我认为你不应该装载500M的数据,如果这样的话很可能使其他程序无法使用,
在windows中可以修改虚存大小,即使这样我看这样做也不太好。
 
你在程序里没法控制物理内存吧,那是由
操作系统控制的.虚拟内存最大是2G,还有2G归操作系统。
不过delphi把所有对象数据放在heap上,是不是你的heap
空间不够用了?
 
你的交换文件多大,把它增大点
 
应用程序大部分用虚拟内存
 
这样说吧,我建立了以下的一个类:
TMyClass = class(TObject)
sBuf : array[0..1023 * 1023] of Char
// 1M bytes
end;

然后用以下循环测试:
var
obj : TMyClass;
List : TList;
I : integer;
begin
List := TList.Create;
try
while true do begin
Obj := TMyClass.Create

List.Add(Obj);
end;
except
ShowMessage(IntToStr(List.Count));
end;
for I := 0 to List.Count - 1 do begin
TMyClass(List.Items).Free;
end;
List.Free;
end;

看看分配到几M时程序会死。
 
我写的DNA拼接程序,在我的机器(512M)上运行时数据量超过30000的时候Windows 2000
就会报错“您的虚拟内存最小值太低...”。我认为只要你的程序使用的空间小于2G,Windows
都应该可以自动进行磁盘缓冲的切换,内存页面的管理对于用户程序来说是完全透明的。
 
既然数据已经到了500M了,我就认为不要直接把全部数据LOAD到内存里面去了。如果你那500MM是一个文件的话,建议你把数据直接映射成内存……
详细的做法请参考一下CSDN上面xrbeck发表的《内存映射文件之剖析》
 
编辑BOOT。INT文件
将multi(0)disk(0)rdisk(0)partition(1)/WINNT="Microsoft Windows 2000 Advanced Server" /fastdetect
改为multi(0)disk(0)rdisk(0)partition(1)/WINNT="Microsoft Windows 2000 Advanced Server" /3G
这样操作系统1G,应用程序可以3G了,你试试

 
procedure GetMemoryManager(var MemMgr: TMemoryManager);
procedure SetMemoryManager(const MemMgr: TMemoryManager);
用这两个函数试一试
我没有弄过,仅供参考
 
我参阅了Borland的文档,说GetMem等函数底层都是基于VirtualAlloc实现的,于是就写了下
列程序来测试,发现在我的256M的机器上可以分配 474 M的内存,为什么,好象比2G少太多了吧?

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
PBlock = ^TBlock;
TBlock = record
buf : array[0..1024 * 1024 - 1] of Byte
//1M
end;

TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
L : TList;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
B : PBlock;
I : integer;
begin
try
L := TList.Create;
I := 0;
while TRUE do begin
GetMem(B,SizeOf(TBlock));
L.Add(B);
Inc(I);
Label1.Caption := '已经分配内存 ' + IntToStr(I) + ' 兆';
Label1.Refresh;
end;
except
for I := 0 to L.Count - 1 do begin
FreeMem(L.Items,SizeOf(TBlock));
end;
L.Free;
end;
end;

{ MemClass }

end.
 
我测试的结果,最多分配了1924M.
应用程序最多能分配大约 2G 内存,指的是虚拟内存。只表示了一种寻址能力。
因为win32中指针32位,有4G空间可用,其中win32把 2G 给了操作系统。
实际上能分配的内存数和你的实际物理内存和你在硬盘上设的交换叶面文件
的大小都有关系,而且系统中其他正在运行的进程也会占一部分存储空间.
 
出现你的这种情况,最大的可能就是硬盘交换文件的最大值设得太小
或者硬盘空间根本不够......
 
2G是寻址能力,xxx M是实际可使用的容量(虚拟内存+物理内存)。
你的硬盘足够大,就可以将虚拟内存设为2G。
 
用临时文件吧,这样你几乎可以无限大的使用
 
你不应该在对象中分配内存,而应该专门设置一个缓冲区,对象中只保存这个缓冲区的指针就可以了,这个缓冲区可以用内存映像文件实现,这样你就不会在Windows交换文件中占太多空间了,存取速度也会略有提高。
 
高难的问题!
 
在内存映射里有一个概念就是最大的映射值不能大于物理内存的,我想你这个问题也是相
当于在物理内存中一下分配太大的内存了,因为物理内存和虚存的转存是有一定的页面交
结规定的,如果你的文件太大500M,这样一下加到物理内存,windows无法完成将超过部
分转成虚存的工作,所以你只能是用内存映射的方式,一次读入一部分的,然后通过指针
控制来完成整个大文件的操作,像photoshop等图形处理软件都是通过内存映射来做的,没
有谁会直接分配500M文件的
 
后退
顶部