gpt4 book ai didi

string - Delphi 应用程序泄漏 AnsiStrings

转载 作者:IT王子 更新时间:2023-10-28 23:32:28 25 4
gpt4 key购买 nike

根据 FastMM4,我目前正在处理的 Delphi 程序泄漏了很多字符串。 AnsiStrings 准确地说:

enter image description here

应用程序 (http://sourceforge.net/projects/orwelldevcpp/) 曾经泄漏更多其他数据类型,但 FastMM4 可以报告实例的创建位置,因此我设法解决了这个问题。奇怪的是,FastMM4 根本不报告这些泄漏的位置。

编辑:它似乎确实如此,请参阅修复的答案。无论如何,问题仍然存在:我到底是怎么泄露这些东西的?

所以,嗯,不幸的是,我不知道要寻找什么。我的意思是,如果这些东西超出范围,它们应该被自动释放(即使它们在堆上)?

我确实设法通过随机评论并查看计数会发生什么来追踪一些泄漏。这是一个例子:

// simply passing it a constant creates a leak...
MainForm.UpdateSplash('Creating extra dialogs...');

procedure TMainForm.UpdateSplash(const text : AnsiString);
begin
if not devData.NoSplashScreen then // even if this branch is NOT taken
SplashForm.Statusbar.SimpleText := 'blablabla' + text;
end;

// And even if the function call itself is placed within a NOT taken branch!

这是另一个泄漏示例:

// Passing this constants produces leaks...
procedure TCodeInsList.AddItemByValues(const a, b, c: AnsiString;...);
var
assembleditem : PCodeIns;
begin
new(assembleditem);
assembleditem^.Caption:=a;
assembleditem^.Line:=b;
assembleditem^.Desc:=c;
...
fList.Add(assembleditem);
end;

// ... even when calling this on WM_DESTROY!
destructor TCodeInsList.Destroy;
var
I: integer;
begin
for I := 0 to fList.Count - 1 do
Dispose(fList[I]);
fList.Free;
inherited Destroy;
end;

// produces leaks!?

这里有很多字符串泄漏问题,但没有一个真正阐明应该寻找什么模式。 Google 也不提供。

编辑:所以,我必须寻找传递的常量。但是为什么呢?

嗯,有什么想法吗?

最佳答案

您不需要显式分配字符串。除了使用引用计数进行修改外,对象或记录的字符串字段也可能泄漏。例如,

type
PRecord = ^TRecord;
TRecord = record
S: string;
end;

procedure TForm1.Button4Click(Sender: TObject);
var
r: PRecord;
begin
GetMem(r, SizeOf(r^));
Initialize(r^);
r.S := ' ';
FreeMem(r);

在上面的例子中,由于记录本身的内存被释放,FastMM将只报告泄露的字符串。


无论如何,FastMM 没有在对话框中显示堆栈跟踪并不意味着它缺少该信息。确保在“FastMM4Options.inc”中定义了 FullDebugModeLogMemoryLeakDetailToFileLogErrorsToFile。然后在可执行文件的目录中查找“[ExecutableName]_MemoryManager_EventLog.txt”文件。

对于上面的例子,FastMM 生成以下文件:

--------------------------------2012/5/27 4:34:46--------------------------------A memory block has been leaked. The size is: 12Stack trace of when this block was allocated (return addresses):40305E 404B5D 404AF0 45C47B 43D726 42B0C3 42B1C1 43D21E 76C4702C [GetWindowLongW]77AE3CC3 [Unknown function at RtlImageNtHeader]The block is currently used for an object of class: UnknownThe allocation number is: 484Current memory dump of 256 bytes starting at pointer address 7EF8DEF8:01 00 00 ......

Now you can run the application, pause it and then search for the addresses. For the above log and the test application, the addresses resolves to:

Stack trace of when this block was allocated (return addresses):40305E    -> _GetMem404B5D    -> _NewAnsiString404AF0    -> _LStrAsg45C47B    -> TForm1.Button4Click (on FreeMem line)43D726    -> TControl.Click... 


edit: Instead of manually looking up addresses, generate a detailed map file through linker options and FastMM will do it (thanks to Mason's comment).


Your edit on the question reflects a quite similar leak like the one in the above example. If the 'fList' is a regular TList, it just holds pointers and have no knowledge of what those pointers points to. Hence when you dispose the pointer, just the memory allocated for the pointer itself is freed, not the fields of the record. So the leaks have nothing to do constants passed to functions but is like the pattern below:

var
assembleditem: PCodeIns;
p: Pointer;
begin
new(assembleditem);
assembleditem^.Caption:='a';
..
p := assembleditem;
Dispose(p);

对于要处理的记录,代码应该将指针类型转换为它的类型:

Dispose(PCodeIns(p));

所以你的“TCodeInsList.Destroy”应该是:

destructor TCodeInsList.Destroy;
var
I: integer;
begin
for I := 0 to fList.Count - 1 do
Dispose(PCodeIns(fList[I]));
fList.Free;
inherited Destroy;
end;


最后,您正在寻找的模式似乎是在寻找代码意图释放具有字符串字段的记录(不太可能的对象)的地方。寻找 Dispose,不太可能 FreeMem,甚至不太可能 FreeInstance 释放 FastMM 显示为分配的内存的对象/记录的内存泄漏可能会有所帮助。

关于string - Delphi 应用程序泄漏 AnsiStrings,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10768152/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com