Delphi 为什么Themes.pas在链接到DLL时泄漏TThemeServices单例

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外接程序,这确实导致了这次泄漏

更新:在XE2中引入VCL样式的更改消除了内存泄漏。所以我想这毕竟是无意的


我今天在Themes.pas中遇到一个VCL内存泄漏。它只适用于DLL。机组最终确定代码如下:

finalization
  if not IsLibrary then
    InternalServices.Free;
InternalServices
是在调用
ThemeServices
函数时按需创建的单例。许多DLL没有UI,因此从未创建此单例。然而,我碰巧有一个Excel的COM外接程序,这确实导致了这次泄漏

这个漏洞并没有特别困扰我,因为这个DLL从来不会从同一个进程重复加载和卸载。我知道如何使用
ThemeServicesClass
全局变量修复泄漏


我的问题是,是否有人能解释为什么这个代码是这样的。它似乎是故意这样编码的。就我的一生而言,我无法对这一故意泄漏做出解释。

一种解释是,在操作系统加载程序锁处于活动状态时执行单元终结部分。在这段时间内,对于允许DLL在不存在死锁风险的情况下执行的操作有很大的限制。

我们也遇到了同样的问题。以下是我们目前为防止项目泄漏所做的工作:

  • 在dll.dpr文件中,将主题添加到uses部分

  • 添加以下内容以清除停机时的泄漏:

    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时才会出现问题。