Delphi 为什么Themes.pas在链接到DLL时泄漏TThemeServices单例
更新:在XE2中引入VCL样式的更改消除了内存泄漏。所以我想这毕竟是无意的Delphi 为什么Themes.pas在链接到DLL时泄漏TThemeServices单例,delphi,Delphi,更新:在XE2中引入VCL样式的更改消除了内存泄漏。所以我想这毕竟是无意的 我今天在Themes.pas中遇到一个VCL内存泄漏。它只适用于DLL。机组最终确定代码如下: finalization if not IsLibrary then InternalServices.Free; InternalServices是在调用ThemeServices函数时按需创建的单例。许多DLL没有UI,因此从未创建此单例。然而,我碰巧有一个Excel的COM外接程序,这确实导致了这次泄漏
我今天在Themes.pas中遇到一个VCL内存泄漏。它只适用于DLL。机组最终确定代码如下:
finalization
if not IsLibrary then
InternalServices.Free;
InternalServices
是在调用ThemeServices
函数时按需创建的单例。许多DLL没有UI,因此从未创建此单例。然而,我碰巧有一个Excel的COM外接程序,这确实导致了这次泄漏
这个漏洞并没有特别困扰我,因为这个DLL从来不会从同一个进程重复加载和卸载。我知道如何使用ThemeServicesClass
全局变量修复泄漏
我的问题是,是否有人能解释为什么这个代码是这样的。它似乎是故意这样编码的。就我的一生而言,我无法对这一故意泄漏做出解释。一种解释是,在操作系统加载程序锁处于活动状态时执行单元终结部分。在这段时间内,对于允许DLL在不存在死锁风险的情况下执行的操作有很大的限制。我们也遇到了同样的问题。以下是我们目前为防止项目泄漏所做的工作:
procedure DLLEntryProc(EntryCode: integer);
begin
case EntryCode of
DLL_PROCESS_DETACH:
begin
ThemeServices.Free;
end;
DLL_PROCESS_ATTACH:
begin
end;
DLL_THREAD_ATTACH:
begin
end;
DLL_THREAD_DETACH:
begin
end;
end;
end;
begin
{$IFDEF DEBUG}
ReportMemoryLeaksOnShutdown := True;
{$ENDIF}
DllProc := @DLLEntryProc;
end.
出于同样的想法,必须有一个很好的理由让它泄漏(indy也故意泄漏了一些东西,或者至少过去是这样),我宁愿忽略它,就像这样:
{$I FastMM4Options.inc}
...
{$IFDEF EnableMemoryLeakReporting}
if IsLibrary then// ThemeServices is leaked when created in a DLL.
RegisterExpectedMemoryLeak(ThemeServices);
{$ENDIF}
啊,我知道装载机锁的问题,并且确实遇到了一些麻烦来解决它,但是我在试图解释这一点时没有记住它。谢谢,我将查看析构函数代码,看看它是否有任何问题。析构函数为缓存的每个主题元素调用
CloseThemeData
,然后调用UxTheme.FreeThemeLibrary
。我认为这可能是个问题,但UxTheme很乐意在其最终版本中调用FreeThemeLibrary
,所以这不可能。没有托管类型的类成员(例如接口)。它有几个状态为打开的QC报告:903688490,66013@Sertac你知道,如果我想不出一个解释,我打算提交一份质量控制报告。这段代码似乎是有意为之,我没想到它会是一个bug,所以我从来没有考虑过看QC。我必须说,对那些QC报告的反应太令人沮丧了。提交者提供了明显泄漏的VCL源代码行,高桥友弘要求提供一个示例项目来复制它。这会让你推迟提交报告!还有其他让你反感的方式。。我知道那种感觉。。。顺便说一句,显然有些记者/评论员为了解决问题将“IsLibrary”设置为false,这让我怀疑代码是否有充分的理由。@David,我刚刚遇到了内存泄漏。您认为在我的库的最后定稿部分调用ThemeServices.Free
安全吗?还是我更愿意使用?我认为两者都可以。但是你真的需要做什么吗。只有反复加载和卸载DLL时才会出现问题。