TTaskBar 内存泄漏
TTaskBar memory leak
Embarcadero 的 TTaskbar 存在内存泄漏。由于我将此控件放在我的表单上,因此每次关闭应用程序时 FastMM 都会报告泄漏。
我试图用这段代码使 FastMM 静音:
procedure TMainForm.FormCreate(Sender: TObject);
begin
fastmm4.RegisterExpectedMemoryLeak(Taskbar);
end;
但这行不通。如何注册此泄漏?
A memory block has been leaked. The size is: 100
This block was allocated by thread 0xC64, and the stack trace (return
addresses) at the time was: 406A52 409A7B 409CAC 4283A0
[System.SysUtils][System][System.SysUtils.FmtStr] 409CC6 40D775
7628A65F
[Unknown function at StretchDIBits] 7731594E
[Unknown function at RtlpNtMakeTemporaryKey] 7731594E
[Unknown function at RtlpNtMakeTemporaryKey] 773168F8
[Unknown function at RtlpNtMakeTemporaryKey] 773168DC
[Unknown function at RtlpNtMakeTemporaryKey]
The block is currently used for an object of class: UnicodeString
The allocation number is: 2209
A memory block has been leaked. The size is: 36
This block was allocated by thread 0xC64, and the stack trace (return
addresses) at the time was: 406A52 407D43 40846A 42CD40
[System.SysUtils][System][System.SysUtils.Exception.CreateFmt] 5DEDD7
[System.Win.TaskbarCore][System.Win][System.Win.TaskbarCore.TTaskbarBase.UpdateTab]
610F00
[Vcl.Taskbar][Vcl][Vcl.Taskbar.CheckMDI] 5DF39F
[System.Win.TaskbarCore][System.Win][System.Win.TaskbarCore.TTaskbarBase.ApplyTabsChanges]
610DB8
[Vcl.Taskbar][Vcl][Vcl.Taskbar.TCustomTaskbar.Initialize]
5EB044
[Vcl.Forms][Vcl][Vcl.Forms.TApplication.Run] 62573A
[MinimalTemplate.dpr][MinimalTemplate][MinimalTemplate.MinimalTemplate][26]
The block is currently used for an object of class: ETaskbarException
The allocation number is: 2207
This application has leaked memory. The small block leaks are (excluding expected leaks registered by pointer):
21 - 36 bytes: ETaskbarException x 1
85 - 100 bytes: UnicodeString x 1
[Vcl.Forms][Vcl][Vcl.Forms.TCustomForm.SetVisible] 5F5010
此代码中的内存泄漏来自 System.Win.TaskbarCore
:
procedure TTaskbarBase.UpdateTab;
var
LpfIsiconic: LONGBOOL;
LHandle: HWND;
LFlags: Integer;
begin
if FTaskbarIsAvailable then
begin
LHandle := GetFormHandle;
if not FRegistered and TaskBar.RegisterTab(LHandle) then
begin
TaskBar.SetTabOrder(LHandle);
TaskBar.SetTabActive(LHandle);
FRegistered := True;
end
else
ETaskbarException.CreateFmt(SCouldNotRegisterTabException, [TaskBar.LastError]);
....
最后一行创建了一个异常,然后什么都不做。异常及其拥有的字符串被泄露。据 FastMM 报道。
如果你能得到它们的地址,你就可以将这些对象注册为泄漏。但是,您不能那样做。无法引用此异常对象。
如果您只是必须避免这种错误报告的泄漏,并且您这样做是有道理的,那么您需要在您的项目中包含 System.Win.TaskbarCore
的固定版本。制作该文件的副本,并将其添加到您的项目中。然后修改代码修复故障。我的猜测是它会像这样:
if not FRegistered then
begin
if TaskBar.RegisterTab(LHandle) then
begin
TaskBar.SetTabOrder(LHandle);
TaskBar.SetTabActive(LHandle);
FRegistered := True;
end
else
raise ETaskbarException.CreateFmt(SCouldNotRegisterTabException, [TaskBar.LastError]);
end;
显然这需要报告给 Embarcadero。我建议您提交错误报告。
另一种解决方法是尽量避免执行伪造的行。我相信如果你从你的 .dfm 文件中删除这一行,你应该避免伪造的行,从而避免泄漏:
Visible = True
干脆去掉那一行,好像是触发器。
请注意,我通过将项目精简到最基本的部分来解决这个问题。为了重现该问题,这是所需的最小 dfm 文件:
object Form1: TMainForm
Visible = True
object Taskbar1: TTaskbar
end
end
而且这个 dfm 文件没有泄漏:
object Form1: TMainForm
object Taskbar1: TTaskbar
end
end
通过将项目削减到最低限度,我找到了触发点。我怎么强调这种最小化复制技术的价值都不为过。
感谢 Remy 找到此故障的 QC 报告:QC#128865
Embarcadero 的 TTaskbar 存在内存泄漏。由于我将此控件放在我的表单上,因此每次关闭应用程序时 FastMM 都会报告泄漏。
我试图用这段代码使 FastMM 静音:
procedure TMainForm.FormCreate(Sender: TObject);
begin
fastmm4.RegisterExpectedMemoryLeak(Taskbar);
end;
但这行不通。如何注册此泄漏?
A memory block has been leaked. The size is: 100
This block was allocated by thread 0xC64, and the stack trace (return addresses) at the time was: 406A52 409A7B 409CAC 4283A0
[System.SysUtils][System][System.SysUtils.FmtStr] 409CC6 40D775 7628A65F
[Unknown function at StretchDIBits] 7731594E
[Unknown function at RtlpNtMakeTemporaryKey] 7731594E
[Unknown function at RtlpNtMakeTemporaryKey] 773168F8
[Unknown function at RtlpNtMakeTemporaryKey] 773168DC
[Unknown function at RtlpNtMakeTemporaryKey]The block is currently used for an object of class: UnicodeString
The allocation number is: 2209A memory block has been leaked. The size is: 36
This block was allocated by thread 0xC64, and the stack trace (return addresses) at the time was: 406A52 407D43 40846A 42CD40
[System.SysUtils][System][System.SysUtils.Exception.CreateFmt] 5DEDD7
[System.Win.TaskbarCore][System.Win][System.Win.TaskbarCore.TTaskbarBase.UpdateTab] 610F00
[Vcl.Taskbar][Vcl][Vcl.Taskbar.CheckMDI] 5DF39F
[System.Win.TaskbarCore][System.Win][System.Win.TaskbarCore.TTaskbarBase.ApplyTabsChanges] 610DB8
[Vcl.Taskbar][Vcl][Vcl.Taskbar.TCustomTaskbar.Initialize] 5EB044
[Vcl.Forms][Vcl][Vcl.Forms.TApplication.Run] 62573A
[MinimalTemplate.dpr][MinimalTemplate][MinimalTemplate.MinimalTemplate][26]The block is currently used for an object of class: ETaskbarException
The allocation number is: 2207This application has leaked memory. The small block leaks are (excluding expected leaks registered by pointer):
21 - 36 bytes: ETaskbarException x 1
85 - 100 bytes: UnicodeString x 1
[Vcl.Forms][Vcl][Vcl.Forms.TCustomForm.SetVisible] 5F5010
此代码中的内存泄漏来自 System.Win.TaskbarCore
:
procedure TTaskbarBase.UpdateTab;
var
LpfIsiconic: LONGBOOL;
LHandle: HWND;
LFlags: Integer;
begin
if FTaskbarIsAvailable then
begin
LHandle := GetFormHandle;
if not FRegistered and TaskBar.RegisterTab(LHandle) then
begin
TaskBar.SetTabOrder(LHandle);
TaskBar.SetTabActive(LHandle);
FRegistered := True;
end
else
ETaskbarException.CreateFmt(SCouldNotRegisterTabException, [TaskBar.LastError]);
....
最后一行创建了一个异常,然后什么都不做。异常及其拥有的字符串被泄露。据 FastMM 报道。
如果你能得到它们的地址,你就可以将这些对象注册为泄漏。但是,您不能那样做。无法引用此异常对象。
如果您只是必须避免这种错误报告的泄漏,并且您这样做是有道理的,那么您需要在您的项目中包含 System.Win.TaskbarCore
的固定版本。制作该文件的副本,并将其添加到您的项目中。然后修改代码修复故障。我的猜测是它会像这样:
if not FRegistered then
begin
if TaskBar.RegisterTab(LHandle) then
begin
TaskBar.SetTabOrder(LHandle);
TaskBar.SetTabActive(LHandle);
FRegistered := True;
end
else
raise ETaskbarException.CreateFmt(SCouldNotRegisterTabException, [TaskBar.LastError]);
end;
显然这需要报告给 Embarcadero。我建议您提交错误报告。
另一种解决方法是尽量避免执行伪造的行。我相信如果你从你的 .dfm 文件中删除这一行,你应该避免伪造的行,从而避免泄漏:
Visible = True
干脆去掉那一行,好像是触发器。
请注意,我通过将项目精简到最基本的部分来解决这个问题。为了重现该问题,这是所需的最小 dfm 文件:
object Form1: TMainForm
Visible = True
object Taskbar1: TTaskbar
end
end
而且这个 dfm 文件没有泄漏:
object Form1: TMainForm
object Taskbar1: TTaskbar
end
end
通过将项目削减到最低限度,我找到了触发点。我怎么强调这种最小化复制技术的价值都不为过。
感谢 Remy 找到此故障的 QC 报告:QC#128865