我有一个主机应用程序,它在启动时加载了十几个库。我想从Delphi 7s默认内存管理器切换到FastMM4的完整版本,以获得更好的内存泄漏报告。
我应该在主机应用程序和库的使用部分中包含FastMM4吗? 那么共享运行时包呢?
一些补充信息:
其他问题:
答案 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运行时包使用已安装的内存管理器。