Delphi 如何确定特定组件或类使用了多少内存?

Delphi 如何确定特定组件或类使用了多少内存?,delphi,memory,components,Delphi,Memory,Components,是否可以在delphi中检索单个组件使用的内存量 我正在从互联网上下载简单的字符串,我看到在下载过程结束时,内存使用量高达1 GB,但当我查看保存的文件(其中包含我下载的所有内容)时,该文件仅在KB范围内,很明显,尽管我销毁了这些组件,但这些组件仍存在一些问题 例如: 编辑: 我怎么知道作为TStringList的“列表”在内存中占用了10MB的空间 谢谢。首先:请耐心等待,这实际上不是您问题的确切答案,但它太大,无法在评论中发布。这段代码是使用FPC编写和编译的,但它可以为您提供一些估计。也许

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

我正在从互联网上下载简单的字符串,我看到在下载过程结束时,内存使用量高达1 GB,但当我查看保存的文件(其中包含我下载的所有内容)时,该文件仅在KB范围内,很明显,尽管我销毁了这些组件,但这些组件仍存在一些问题

例如:

编辑:

我怎么知道作为TStringList的“列表”在内存中占用了10MB的空间


谢谢。

首先:请耐心等待,这实际上不是您问题的确切答案,但它太大,无法在评论中发布。这段代码是使用FPC编写和编译的,但它可以为您提供一些估计。也许有人知道如何将其移植到Delphi

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,1MB(3280005字节)(ansi编码)

我认为比较前后的内存使用情况是解决这个问题的方法,因为没有简单的方法可以看出在事件发生后一段代码分配了什么内存。。。例如,对于上面的字符串列表,类本身只会占用少量内存,因为它由指向其他分配(即字符串数组)的指针组成,而该类本身是指向实际字符串的指针数组。。。这是一个相对简单的例子

无论如何,这可以通过FastMM完成,其函数如下

使用
FastMM4;
函数CheckAllocationBy(const AProc:TProc):NativeUInt;
变量
Loriginalaallocated:NativeUInt;
lFinalAllocated:本地单元;
lUsage:TMemoryManagerUsageSummary;
开始
GetMemoryManagerUsageSummary(lUsage);
LoriginAlaAllocated:=lUsage.AllocatedBytes;
尝试
澳大利亚审慎监管委员会;
最后
GetMemoryManagerUsageSummary(lUsage);
LFINALLOCATED:=lUsage.AllocatedBytes;
结束;
结果:=lFinalAllocated-lOriginalAllocated;
结束;
可以这样使用

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

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

我想您需要这些信息用于调试目的?(看起来组件确实有一些内存问题…)我想你已经知道全局变量之类的事情了?有趣的是,我如何打开它?肯:“InstanceSize不是你想要的”,Xaid:“我尝试过InstanceSize,但它不是我想要的。”请展示一个完整的程序。否则这只会导致徒劳的猜测。如果我理解正确,您有一个错误的组件泄漏内存。如果您是组件的作者,或者您可以访问源代码,那么您应该尝试修复它。否则,如果可能的话,您应该联系开发人员。这并不能回答所提出的问题,即“特定组件使用多少内存?”例如,向stringlist添加一些10M字符串。您已经创建了一个空字符串列表,然后添加了一个已知长度的字符串。请使用这些信息来预测如果您将10M随机长度的字符串添加到stringlist中需要多少内存。(不是相同长度的字符串-随机长度字符串。)==3==3568 3568==4==8837104 4643776文件“tolstoy-war-peace.txt”,ansi编码,大小=3,1MB。这不是10M随机字符串;这是一组固定大小的数据(3.1Mb)。现在用1万组其他数据重复1万次,并告诉我
TStringList
的大小。正如我在对原始帖子的评论中所说的,你不能这样做,因为你需要知道它目前包含的数据信息。阅读原始问题的意图以及对它的评论。@KenWhite似乎我们彼此不理解:)我的测试文本文件是由49839个“随机”字符串组成的(请原谅,列夫·托尔斯泰!)我只是没有任何其他大小合适的文本文件(除了3 Gb左右的数据库转储无法加载到32位应用程序中)或者你的意思是
对于i:=0到1000000,确实要从sl.LoadFromFile('file'+IntToStr(i));{testmemory}结束;
?@DavidHeffernan问题是:“在delphi中检索单个组件使用的内存量是否可能?”在我上面的评论中,有几种可能的解决方案之一:比较“之前”和“之后”使用的内存。我刚刚发布了在FP上编写的示例(不幸的是,我有一段时间没有使用Delphi)。是的,比较似乎是最好的方法。谢谢!似乎是合法的,但在多线程环境中,当另一个线程可能同时增加内存消耗时,这将如何工作?简单地说……不会。如果进行调试,可以在初始使用检查之前冻结其他线程以确保(如果需要该级别的保证)…尽管这可能会导致锁定。此外,可能是另一个线程代表测试中的代码分配流失的内存。问题是我们不知道组件的内部工作。这只是另一种想法。考虑封装库的组件时,情况可能会更糟(比如TPerlRegEx可以吗?)。我不认为这个库中分配的内存也可以从本地内存管理器中看到……尽管它会消耗进程可用的内存。哦,好吧。更多值得思考的地方。
lAllocatedBytes := CheckAllocationBy(
  procedure
  begin
    list:=TStringList.Create;
    list.LoadFromFile('10MB_of_Data.txt');
    list.Free;
  end);