4

是否可以检索 delphi 中单个组件使用的内存量?

我正在从互联网上下载简单的字符串,我发现在下载过程结束时内存使用量高达千兆字节,但是当我查看包含我下载的所有内容的保存文件时,文件只有千字节范围,很明显,这些组件发生了一些事情,即使我破坏了它们。

例子:

编辑:

procedure TForm1.OnCreate(Sender: TObject);
  var list: TStringList;
begin
  list:=TStringList.Create;
  list.LoadFromFile('10MB_of_Data.txt');
  list.destroy;
end;

我怎么知道作为 TStringList 的“列表”正在使用 10 MB 的内存空间?

谢谢你。

4

2 回答 2

4

我认为比较之前和之后的内存使用情况是解决这个问题的方法,因为没有简单的方法可以查看事后代码块分配了哪些内存......例如,使用上面的字符串列表,类它本身只会占用少量内存,因为它由指向其他分配的指针(即字符串数组)组成,并且它本身是指向实际字符串的指针数组......这是一个相对简单的情况.

无论如何,这可以使用 FastMM 来完成,其功能如下......

uses
  FastMM4;

function CheckAllocationBy(const AProc: TProc): NativeUInt;
var
  lOriginalAllocated: NativeUInt;
  lFinalAllocated: NativeUInt;
  lUsage: TMemoryManagerUsageSummary;
begin
  GetMemoryManagerUsageSummary(lUsage);
  lOriginalAllocated := lUsage.AllocatedBytes;
  try
    AProc;
  finally
    GetMemoryManagerUsageSummary(lUsage);
    lFinalAllocated := lUsage.AllocatedBytes;
  end;
  Result := lFinalAllocated - lOriginalAllocated;
end;

并且可以这样使用...

lAllocatedBytes := CheckAllocationBy(
  procedure
  begin
    list:=TStringList.Create;
    list.LoadFromFile('10MB_of_Data.txt');
    list.Free;
  end);

这将告诉您您的字符串列表留下了多少(有趣的是,我在第一次重复调用时得到 40 个字节,之后在调用前后查阅使用日志后得到 0 个字节,这是在第一次调用时创建的两个编码类) . 如果您想检查泄漏内存的分配位置,使用 FastMM 也很简单(尽管我同意上述观点,如果它是第 3 方,那不应该是您的问题)。

于 2013-03-26T08:54:18.403 回答
1

首先:请耐心等待,这实际上并不能完全回答您的问题,但它太大了,无法在评论中发布。此代码是使用 FPC 编写和编译的,但它可以为您提供一些估计。可能有人知道如何将它移植到德尔福。

program project4;

uses
    SysUtils,
    Classes;

var
    p: Pointer;
    sl: TStringList;
var
    a: TFPCHeapStatus;
begin
    a := GetFPCHeapStatus;
    writeln('== 1 ==');
    //writeln(a.MaxHeapSize);
    writeln(a.MaxHeapUsed);
    //writeln(a.CurrHeapSize);
    writeln(a.CurrHeapUsed);
    //writeln(a.CurrHeapFree);

    GetMem(p, 1024);

    a := GetFPCHeapStatus;
    writeln('== 2 ==');
    writeln(a.MaxHeapUsed);
    writeln(a.CurrHeapUsed);

    sl := TStringList.Create;

    a := GetFPCHeapStatus;
    writeln('== 3 ==');
    writeln(a.MaxHeapUsed);
    writeln(a.CurrHeapUsed);

    sl.Add('To beer or not to beer? That is the question!');

    a := GetFPCHeapStatus;
    writeln('== 4 ==');
    writeln(a.MaxHeapUsed);
    writeln(a.CurrHeapUsed);

    Readln;
end.

和输出:

== 1 ==
2448
2448
== 2 ==
3488
3488
== 3 ==
3568
3568
== 4 ==
3616
3616

另一个带有大文本文件的测试:

sl.LoadFromFile('tolstoy - war and peace.txt');

a := GetFPCHeapStatus;
writeln('== 4 ==');
writeln(a.MaxHeapUsed);
writeln(a.CurrHeapUsed);  

输出:

== 3 ==
3568
3568
== 4 ==
8837104
4643776

文件大小:3,1 Mb(3 280 005 字节)(ansi 编码)

于 2013-03-25T21:18:00.283 回答