释放的 TStringList 在 FastMM4 报告中算作内存泄漏的原因
Reason why a freed TStringList counts as memory leak in the FastMM4 report
在我的一个应用程序的任务管理器中注意到奇怪的内存行为后,我开始使用 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;
FastMM4 堆栈报告告诉我泄漏从
开始
ResourcesList := TStringList.Create;
即使我 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".
为了研究上面的泄漏,我评论说我 99% 的代码都集中在第一个报告的泄漏上,事实上,一个在应用程序的初始化部分。
这怎么可能?
更新
代码的工作版本避免调用 TStringList.Create
,因为 GetResourceList
方法已经 returns 正确创建 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
[...]
你有两个问题:
1
1. ResourcesList := TStringList.Create;
2. // get resource files list
3. ResourcesList := GetResourceList;
在第 1 行,您创建了一个新的 TStringList
对象并将地址保存到本地 ResourcesList
变量中。
但是在第 3 行,我想 GetResourceList
函数也创建了一个新的 TStringList
对象,然后你重写局部 ResourcesList
变量,让它指向这个,新的, 反对。
这意味着现在没有变量 指向您创建的第一个TStringList
对象。因此,它永远被泄露了。
你要的是这个:
// get resource files list
ResourcesList := GetResourceList;
2
你的代码本质上是
try
ResourcesList := TStringList.Create; //or GetResourceList;
// Use the list
finally
ResourcesList.Free
end;
这是一个非常常见的错误。如果 TStringList.Create
构造函数失败(或 GetResourceList
函数),部分创建的 TStringList
对象将自动释放(或希望由 GetResourceList
函数释放),但随后出现异常停止执行,因此没有值写入 ResourcesList
.
因此,ResourcesList.Free
将 运行 随机指针上的析构函数,因为未初始化非托管类型的局部变量。
你必须做
ResourcesList := TStringList.Create; //or GetResourceList;
try
// Use the list
finally
ResourcesList.Free
end;
在我的一个应用程序的任务管理器中注意到奇怪的内存行为后,我开始使用 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;
FastMM4 堆栈报告告诉我泄漏从
开始ResourcesList := TStringList.Create;
即使我 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".
为了研究上面的泄漏,我评论说我 99% 的代码都集中在第一个报告的泄漏上,事实上,一个在应用程序的初始化部分。
这怎么可能?
更新
代码的工作版本避免调用 TStringList.Create
,因为 GetResourceList
方法已经 returns 正确创建 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
[...]
你有两个问题:
1
1. ResourcesList := TStringList.Create;
2. // get resource files list
3. ResourcesList := GetResourceList;
在第 1 行,您创建了一个新的 TStringList
对象并将地址保存到本地 ResourcesList
变量中。
但是在第 3 行,我想 GetResourceList
函数也创建了一个新的 TStringList
对象,然后你重写局部 ResourcesList
变量,让它指向这个,新的, 反对。
这意味着现在没有变量 指向您创建的第一个TStringList
对象。因此,它永远被泄露了。
你要的是这个:
// get resource files list
ResourcesList := GetResourceList;
2
你的代码本质上是
try
ResourcesList := TStringList.Create; //or GetResourceList;
// Use the list
finally
ResourcesList.Free
end;
这是一个非常常见的错误。如果 TStringList.Create
构造函数失败(或 GetResourceList
函数),部分创建的 TStringList
对象将自动释放(或希望由 GetResourceList
函数释放),但随后出现异常停止执行,因此没有值写入 ResourcesList
.
因此,ResourcesList.Free
将 运行 随机指针上的析构函数,因为未初始化非托管类型的局部变量。
你必须做
ResourcesList := TStringList.Create; //or GetResourceList;
try
// Use the list
finally
ResourcesList.Free
end;