FastMM和动态加载的DLL

时间:2010-06-07 12:10:07

标签: delphi dll fastmm

我有一个主机应用程序,它在启动时加载了十几个库。我想从Delphi 7s默认内存管理器切换到FastMM4的完整版本,以获得更好的内存泄漏报告。

我应该在主机应用程序和库的使用部分中包含FastMM4吗? 那么共享运行时包呢?


一些补充信息:

  • 我们有一个exe和> 20个dll。每个人都在共享一个运行时包。
  • 我们今天不使用sharemem。不是我知道的。 ShareMem不包含在e斗机或者我今天快速查看的dll中。

其他问题:

  • 我可以在所有项目的fastmems inc文件中使用相同的选项,还是exe和dll需要不同的设置?

6 个答案:

答案 0 :(得分:8)

摘自FastMM4options.inc文件。

对我来说,这意味着如果所有的包,dll和可执行文件都是用ShareMM编译的,那么应该可以替换Delphi 7s的默认内存管理器。

  

{-----------------------内存管理员   分享   选项------------------------}

     

{允许共享内存管理器   主应用程序和DLL之间   这也是用FastMM编译的。   这允许您传递动态数组   和DLL函数的长字符串   提供两者都编译使用   FastMM。只有在分享时,分享才有效   应该分享的图书馆   内存管理器是用编译的   “AttemptToUseSharedMM”选项设置。   请注意,如果主应用程序是   单线程和DLL是   您必须设置的多线程   主要的IsMultiThread变量   应用程序为true或将崩溃   何时发生线程争用。注意   那个静态链接的DLL文件是   在主要之前初始化   应用,所以主要应用   最终可能会静态共享   加载DLL的内存管理器而不是   另一种方式。 }

     

{。$ define ShareMM}

     

{允许共享内存管理器   由DLL与其他DLL(或主要的   应用程序,如果这是静态的   加载的DLL)也被编译   使用FastMM。设置此选项   关心动态加载的DLL,   因为如果是共享的DLL   它的MM被卸载和任何其他DLL   仍在分享MM然后   应用程序将崩溃。这个设置   仅与DLL库相关   并且还要求ShareMM设置为   有任何影响。只分享   如果所谓的图书馆工作   分享内存管理器了   编译了   “AttemptToUseSharedMM”选项设置。   请注意,如果DLL是静态的   链接然后他们将被初始化   在主要申请之前和   那么DLL实际上会分享它的MM   与主要应用程序。这个   除非ShareMM,否则选项无效   也设置。}

     

{。$ define ShareMMIfLibrary}

     

{定义此项以尝试分享   MM的主要应用还是其他   加载DLL在同一个进程中   用ShareMM编译编译。什么时候   共享内存管理器,内存   分享者造成的泄密不会   自动释放。考虑到   帐户静态链接的DLL   在主要之前初始化   应用程序,所以设置共享   相应的选项。}

     

{。$ define AttemptToUseSharedMM}

     

{定义此项以向后启用   内存管理器的兼容性   Delphi 2006使用的共享机制   和2007年,以及较旧的FastMM   版本。}

     

{$限定   EnableBackwardCompatibleMMSharing}

答案 1 :(得分:3)

您正在寻找的是SimpleShareMem。它包含在FastMM包中。确保您的应用和DLL在使用子句的顶部使用它以及FastMM4。这可以确保它们共享相同的堆而不是使用单独的堆。

当然,只有当您要在应用程序和库之间传递动态内存(例如字符串或对象)时,才需要共享内存。如果没有,那么你不需要SimpleShareMem,但我仍然建议将库作为内存管理器切换到FastMM,以提高性能和稳定性。

答案 2 :(得分:1)

因为“每个人都在共享一个运行时包。”我推荐我正在使用的方法。简单地说,将FastMM4添加到您的共享运行时包中(当然,您需要在每个库和主机应用程序中将FastMM4置于“using”声明中)。 这种方式有一些优点,如:

  • 打开/关闭FullDebugMode的简单方法[当然还有其他选项]。不需要重新编译项目,仅重新编译共享包就足以在整个应用程序(包括dll)中切换FullDebugMode,因为FastMM只实例化一次。

  • 没有版本控制问题。当您更新FastMM(一旦使用,它成为整个应用程序和插件的关键组件),您不必再次发布整个构建(app&插件)。再一次,更新共享包就足够了。

  • 卸载插件时没有内存管理器问题。卸载第一个插件库后,我遇到了一些卸载FastMM的问题,从而导致应用程序关闭时出现大量错误。

  • 没有跟踪问题 - 如果发生任何内存泄漏或其他内存问题,即使DLL代码中出现错误,也会为您提供有效的调用堆栈。

以下是我在FastMM4Options.inc中使用的(非标准)选项,以便让整个工作如上所述。

{$ define NeverUninstall} {$ define UseRuntimePackages} {。$ define ShareMM}

我相信其余部分保持不变,但如果出现问题,这里是完整的文件: http://pastebin.4programmers.net/693

答案 3 :(得分:0)

Afaik有一个sharemm,一个版本的fastmm可以分享DLL bounderies。

答案 4 :(得分:0)

如果您的应用程序是使用运行时包编译的,则不需要执行其他操作,因为运行时包始终只使用一个内存管理器。您只需要指定一次您选择的内存管理器,最好在主应用程序代码中指定使用列表中的第一个单元。所有其他运行时包都不需要修改,它们将自动使用正确的内存管理器,无论内存管理器是什么。

如果您的应用程序是在没有运行时包的情况下编译的,那么每个dll都有自己的内存管理默认情况下,它们都使用默认的内存管理器,如果我没记错,那就是共享MM,也就是说,你可以传输字符串,例如dlls和dlls。如果要将默认MM替换为另一个共享MM,则需要将新内存管理器作为每个dll或exe中使用列表中的第一个单元包含在内。

不同之处在于,运行时包共享发生在包级别。即使是非共享MM也会被共享。没有运行时包,每个DLL都使用一个单独的MM,只有当这些独立的内存管理器合作时才会共享。

我的观点是,除非你的应用程序与dll非常密切地交互(阅读:在dll中有表单和组件),最好的方法不是依赖共享内存管理器,而是要正确管理内存,跟踪谁在您实例化它们的同一个库中创建了什么并删除了对象。这并不难。只返回接口而不是对象,返回短串(固定长度)或将数据复制到提供的缓冲区而不是返回字符串,依此类推。不要返回被调用者释放的东西,不要接受被调用者必须释放的东西,并且你基本上是安全的。这不仅可以解决所有可能的内存管理器问题,还可以让你用任何语言编写dll。

答案 5 :(得分:0)

Ypu有两种选择:继续使用ShareMem单元和您在FastMM发行版中找到的BorldMM.dll替换,或修改两者可执行文件和DLL以包含FastMM内存管理器,方法是放置作为第一个单位。您还应该根据自己的需要定制一些在FastMM4Options.inc中找到的$ DEFINE,它们在那里得到了很好的解释。 AFAIK运行时包使用已安装的内存管理器。