pro*_*tor 3 delphi memory-leaks fastmm
FastMM报告此行是内存泄漏的来源:
StrClassName := MidStr (curLine, length(START_OF_CLASSNAME)+1, length(curline)+1)
Run Code Online (Sandbox Code Playgroud)
这是怎么回事与Copy和MidStr?这只是一个Delphi 2007编译器的bug,还是以后的版本也有这个问题?这里是链接到FastMM报告的副本,以及像我的应用程序是如何显示这些类型的报告.看,为了显示VirtualTreeView我需要新数据类型的节点.我称之为TMemoryLeak.当我解析报告时,我给出了TMemoryLeak一个类名,callstack,它的大小等等.但是当应用程序关闭,FastMM启动时,上面的复制行似乎泄漏了内存.我释放callstack的大小,整个对象,但ClassName字段是一个字符串总是韭菜内存.
更新(来自评论)
这是声明和构造函数以及解构器.至于生命周期 - 一旦对象用于显示节点树,就会调用对象的解构器,之后它们就会被淘汰,并且被释放(我希望).
TMemoryLeak = class(TObject)
private
fID :integer;
fSize :integer;
fTotalSize :integer;
fCallStack :TStringList;
fClassName :string;
fRepeatedInstance:integer;
public
property ID :integer read fID write fID;
property TotalSize :Integer read fTotalSize write fTotalSize;
property Size :integer read fSize write fSize;
property CallStack :TStringList read fCallStack write fCallStack;
property ClassName :string read fClassName write fClassName;
property RepeatedInstance :integer read fRepeatedInstance write fRepeatedInstance;
class function Equal(xA: TMemoryLeak; xB: TMemoryLeak): Boolean;
procedure clear;
constructor create;
destructor destroy; override;
end;
TMemoryLeakList=class(TObjectList)
private
fSortType :TMlSortType;
fSortDirection :TMLSortDirection;
fTotalLeakSize :integer;
fClassName :string;
fRepeatedInstance :Integer;
fID :Integer;
function GetItem(Index: Integer): TMemoryLeak;
procedure SetItem(Index: Integer; const Value: TMemoryLeak);
public
property Items[Index: Integer]:TMemoryLeak read GetItem write SetItem; default;
property TotalLeakSize :integer read fTotalLeakSize write fTotalLeakSize;
property SortType :TMLSortType read fSortType write fSortType;
property SortDirection :TMLSortDirection read fSortDirection write fSortDirection;
property ClassName :string read fClassName write fClassName;
property RepeatedInstance :integer read fRepeatedInstance write fRepeatedInstance;
property ID :Integer read fID write fID;
function Add(AObject: TMemoryLeak): Integer;
procedure Clear();
procedure Sort;
constructor create;
destructor destroy; override;
end;
constructor TMemoryLeak.create;
begin
inherited;
fCallStack := TStringList.create;
fRepeatedInstance:=0;
end;
destructor TMemoryLeak.destroy;
begin
clear;
end;
procedure TMemoryLeak.clear;
begin
fCallStack.Clear;
end;
class function TMemoryLeak.Equal(xA, xB: TMemoryLeak): Boolean;
var i:Integer;
begin
Result:=False;
if xA.ClassName = xb.ClassName then
begin
if xA.size = xb.size then
begin
if xA.CallStack.Count = xB.CallStack.Count then
begin
for i := 0 to xa.CallStack.Count - 1 do
begin
if CompareStr(xA.CallStack[i], xB.CallStack[i]) <> 0 then
begin
break;
end;
end;
if i = xa.CallStack.Count then
Result:=True;
end
end
end
end;
{ TMemoryLeakList }
constructor TMemoryLeakList.create;
begin
inherited;
fSortType :=stID;
fSortDirection :=sdAsc;
fClassName :='';
fRepeatedInstance :=0;
end;
destructor TMemoryLeakList.destroy;
begin
Clear;
end;
procedure TMemoryLeakList.Clear;
var i : Integer;
begin
for i := 0 to Count - 1 do
Items[i].clear;
end;
Run Code Online (Sandbox Code Playgroud)
Dav*_*nan 11
有意义的解释是你有内存泄漏.
我认为您对FastMM泄漏报告的工作原理有误解.您似乎从泄漏报告中推断出Copy,MidStr等等是造成泄漏的原因.事实并非如此.分配内存但未随后解除分配时会报告泄漏.在类似Copy和的函数的情况下MidStr,他们的工作是创建新的字符串,这自然涉及内存的分配.报告泄漏是因为为了保存字符串缓冲区而创建的内存未被释放.当其余代码无法释放该内存时,它不是Copy或者MidStr是分配函数的错误.
Delphi 2007是一个成熟的产品,已知字符串的内存管理是正确的.也许你做一些手动内存复制,绕过字符串的引用计数.你是否nil通过调用设置一些变量/字段FillChar?你是在处理记录FreeMem而不是Dispose?前者不会减少字符串引用计数.这样的事情可能是泄漏的原因.
查看您发布的代码的摘录,这是一个问题:
destructor TMemoryLeakList.destroy;
begin
Clear;
end;
Run Code Online (Sandbox Code Playgroud)
您无法调用继承的析构函数.这意味着列表的成员不会被销毁.这解释了为什么你的字符串没有被销毁.
实际上,您不需要为列表类提供析构函数.只需删除它,让继承的TObjectList析构函数完成工作.由于OwnsObjects默认为True,列表中的任何成员一旦从列表中删除,并且列表本身被销毁时就会被销毁.
如果您的Clear方法实际清除了列表,那么就会发生这种情况.但你Clear不是真的Clear.Clear预计容器中的真实内容将删除所有成员.您应该删除您的Clear并依赖继承的版本.
在TMemoryLeak,您也无法调用继承的析构函数.并且也无法销毁该类拥有的字符串列表实例.
总而言之,我会像这样编写这些构造函数和析构函数:
constructor TMemoryLeak.Create;
begin
inherited;
fCallStack := TStringList.Create;
end;
destructor TMemoryLeak.Destroy;
begin
fCallStack.Free;
inherited;
end;
constructor TMemoryLeakList.Create;
begin
inherited;//by default OwnsObjects is set to True, list manages member lifetime
fSortType :=stID;
fSortDirection :=sdAsc;
end;
Run Code Online (Sandbox Code Playgroud)
然后删除destructor,并删除Clear方法.继承的版本TObjectList就足够了.
在评论中,您声明:
一旦使用对象显示节点树,就会调用对象的析构函数.在那之后它们已经过时,并且被解除分配(我希望).
我会说这很有可能没有帮助.由于您在OwnsObjects模式下创建了对象列表,因此您根本不应该破坏列表的成员.您已经要求列表本身执行此操作.你不能两个都这样做.并且"我希望"的评论并没有让我充满信心,这段代码是正确的.
由于我们无法看到您的所有代码,因此我很难确定这是它的全部问题.
底线是您的代码有泄漏.相信FastMM!
| 归档时间: |
|
| 查看次数: |
1514 次 |
| 最近记录: |