program Project4;
{$APPTYPE CONSOLE}
{$R *.res}
uses
psAPI,
Winapi.Windows,
System.SysUtils;
type
TSimpleTestClass = class
buffer: TArray<string>;
end;
TMatrixTestClass = class
buffer: TArray<TArray<string>>;
end;
function CurrentProcessMemory: Cardinal;
var
MemCounters: TProcessMemoryCounters;
begin
MemCounters.cb := SizeOf(MemCounters);
GetProcessMemoryInfo(GetCurrentProcess, @MemCounters, sizeOf(MemCounters));
OutputDebugString(PChar(MemCounters.WorkingSetSize.ToString()));
end;
function GenerateRandomString(const ALength: Integer; const ACharSequence: String = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'): String;
var
Ch, SequenceLength: Integer;
begin
SequenceLength := Length(ACharSequence);
SetLength(Result, ALength);
Randomize;
for Ch := Low(Result) to High(Result) do
Result[Ch] := ACharSequence.Chars[Random(SequenceLength)];
end;
var
simpleObj: TSimpleTestClass;
matrixObj: TMatrixTestClass;
i: Integer;
begin
try
CurrentProcessMemory();
simpleObj := TSimpleTestClass.Create();
SetLength(simpleObj.buffer, 10000);
for i := 0 to 9999 do simpleObj.buffer[i] := GenerateRandomString(32);
simpleObj.Free();
CurrentProcessMemory();
matrixObj := TMatrixTestClass.Create();
SetLength(matrixObj.buffer, 10000);
for i := 0 to 9999 do begin
SetLength(matrixObj.buffer[i], 1);
matrixObj.buffer[i][0] := GenerateRandomString(32);
end;
matrixObj.Free();
CurrentProcessMemory();
matrixObj := nil; // For breakpoint
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
我一直在用上面的代码测试一些东西,似乎类中的 TArray 没有被释放。 这很奇怪,因为据我所知,TArray 和 string 都是引用计数。那么,当我的类的实例为 时,为什么它们没有在这里被释放呢?
编辑:很奇怪的是,第二次运行使用的内存比第一次少得多,我相信那里有一些编译器优化。我尝试使用随机字符串,但没有改变。
您正在进行一个错误的假设 - 当您在 Delphi 中释放内存时,它会立即释放回操作系统。事实并非如此。
Delphi 中的内存管理器分配各种大小的块,并且通过从操作系统分配更大的块来在内部处理小分配(我相信内存管理器使用三种不同的块大小,但不要相信我的话)关于这个问题的福音),然后从这个更大的块进行子分配(现在在应用程序中的内存管理器的控制下)。
当您在 Delphi 中释放内存时,它在内部被标记为空闲内存以供以后分配使用,但它仍然由您的程序拥有(从操作系统中可以看出)。
因此,查询进程从操作系统获取了多少内存的函数不会被调整,除非它所属的内部内存块已完全清空,并且 - 我认为 - 是我提到的三个块大小中的大尺寸.
这是为了优化 - 不断分配和释放操作系统内存将对速度产生重大影响,因此内存管理器尝试平衡分配/释放操作系统内存的时间与应用程序的内存消耗。