LaB*_*cca 2 delphi memory-leaks tstringlist fastmm delphi-2010
在注意到我的一个应用程序的任务管理器中出现奇怪的内存行为后,我开始使用 FastMM4 调查内存泄漏。刚打开三张表格就发现了1000多个。我希望能够在一个地方找到原因
在一种情况下,即使总是在finally块中释放TStringList(总是到达),FastMM4也会报告内存泄漏:
function GetMatchingResourceFileName(MatchingString:string) : string;
var
ResourcesList: TStringList;
I : Integer;
begin
Result := '';
try
ResourcesList := TStringList.Create;
// get resource files list
ResourcesList := GetResourceList;
//search for matching file name
for I := 0 to ResourcesList.Count-1 do
begin
if Pos(MatchingString,ResourcesList.Strings[I]) > 0 then
begin
Result := ResourcesList.Strings[I];
break;
end;
end;
finally
ResourcesList.Free;
ResourcesList:= nil;
end;
end;
Run Code Online (Sandbox Code Playgroud)
FastMM4 堆栈报告告诉我泄漏是从
ResourcesList := TStringList.Create;
Run Code Online (Sandbox Code Playgroud)
即使我 100% 确定已ResourcesList.Free;
执行,我也会看到内存泄漏。
当我关闭应用程序时,我看到了报告:
---------------------------
myProject.exe: Memory Leak Detected
---------------------------
This application has leaked memory. The small-block leaks are (excluding expected leaks registered by pointer):
85 - 100 bytes: System.Classes.TStringList x 1
Note: Memory leak detail is logged to a text file in the same folder as this application. To disable this memory leak check, undefine "EnableMemoryLeakReporting".
Run Code Online (Sandbox Code Playgroud)
为了研究上面的泄漏,我将 99% 的代码集中在第一个报告的泄漏上,事实上,是应用程序的初始化部分中的泄漏。
这怎么可能?
更新
代码的工作版本避免了调用TStringList.Create
,因为该GetResourceList
方法已经返回了正确创建的TStringList
,以下代码现在是无泄漏的:
function GetMatchingResourceFileName(MatchingString:string) : string;
var
ResourcesList: TStringList;
I : Integer;
begin
Result := '';
try
ResourcesList := GetResourceList;
//search for matching file name
for I := 0 to ResourcesList.Count-1 do
[...]
Run Code Online (Sandbox Code Playgroud)
你有两个问题:
1. ResourcesList := TStringList.Create;
2. // get resource files list
3. ResourcesList := GetResourceList;
Run Code Online (Sandbox Code Playgroud)
在第 1 行,您创建一个新TStringList
对象并将其地址保存在局部ResourcesList
变量中。
但在第 3 行,我认为该GetResourceList
函数还创建了一个新TStringList
对象,然后重写局部ResourcesList
变量,使其指向这个新对象。
这意味着现在没有变量指向TStringList
您创建的第一个对象。因此,它永远被泄露。
你想要的是这样的:
// get resource files list
ResourcesList := GetResourceList;
Run Code Online (Sandbox Code Playgroud)
你的代码本质上是
try
ResourcesList := TStringList.Create; //or GetResourceList;
// Use the list
finally
ResourcesList.Free
end;
Run Code Online (Sandbox Code Playgroud)
这是一个非常常见的错误。如果TStringList.Create
构造函数(或GetResourceList
函数)失败,则部分创建的TStringList
对象将自动释放(或希望由GetResourceList
函数释放),但随后异常会停止执行,因此不会将任何值写入ResourcesList
.
因此,ResourcesList.Free
将在随机指针上运行析构函数,因为非托管类型的局部变量未初始化。
你必须做
ResourcesList := TStringList.Create; //or GetResourceList;
try
// Use the list
finally
ResourcesList.Free
end;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
315 次 |
最近记录: |