FastMM 和动态加载 DLL
我有一个主机应用程序,它在启动时加载十几个库。我想从 Delphi 7s 默认内存管理器切换到 FastMM4 的完整版本,以获得更好的内存泄漏报告。
我应该在主机应用程序和库的使用部分中包含 FastMM4 吗? 共享运行时包怎么样?
一些补充信息:
- 我们有 1 个 exe 和超过 20 个 dll。每个人都共享一个运行时包。
- 我们今天不使用 sharemem。据我所知并非如此。 ShareMem 不包含在我今天快速查看的 8 个 exe 或 dll 中。
其他问题:
- 我可以在所有项目中的 fastmems inc 文件中使用相同的选项吗?或者 exe 和 dll 是否需要不同的设置?
I have a host application, that loads a dozen of libraries at start up. I want to switch from Delphi 7s default memory manager to the full version of FastMM4 for better mem leak reporting.
Should I include FastMM4 in the uses section of both the host application and the libraries?
What about shared runtime packages?
Some added information:
- We have one exe and >20 dlls. Everyone is sharing a single runtime package.
- We do not use sharemem today. Not that I know about. ShareMem is not included in eighter the exe or the dlls that I had a quick look at to day.
Additional questions:
- Can I use the same options inside fastmems inc file in all projects, or do the exe and the dll need different settings?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
摘自
FastMM4options.inc
文件。对我来说,这意味着如果您的所有包、dll 和可执行文件都是使用 ShareMM 编译的,那么应该可以替换 Delphi 7s 默认内存管理器。
Excerpt from
FastMM4options.inc
file.To me it means that if all your packages, dll's and executables are compiled with ShareMM, it should be possible to replace the Delphi 7s default memory manager.
您正在寻找的内容称为 SimpleShareMem。它包含在 FastMM 包中。确保您的应用程序和 DLL 都在使用它以及 uses 子句顶部的 FastMM4。这确保它们都共享相同的堆,而不是使用单独的堆。
当然,只有当您要在应用程序和库之间传递动态内存(例如字符串或对象)时,才需要共享内存。如果没有,那么您不需要 SimpleShareMem,但我仍然建议将库切换到 FastMM 作为内存管理器,以提高性能和稳定性。
What you're looking for is called SimpleShareMem. It's included in the FastMM package. Make sure both your app and your DLLs are using it as well as FastMM4 at the top of their uses clause. That makes sure they all share the same heap instead of using separate ones.
Of course, shared memory is only necessary if you're going to be passing dynamic memory between the app and the libraries, such as strings or objects. If not, then you don't need SimpleShareMem, but I'd still recommend to switch the libraries to FastMM as the memory manager for increased performance and improved stability.
因为“每个人都共享一个运行时包”。我推荐我正在使用的方法。只需将 FastMM4 添加到共享运行时包中(当然,无论如何,您都需要将 FastMM4 放入每个库和主机应用程序中的“using”声明中)。
这种方式有一些优点,例如:
打开/关闭 FullDebugMode 的简单方法[当然还有其他选项]。无需重新编译项目,仅重新编译共享包就足以在整个应用程序(包括 dll)中切换 FullDebugMode,因为 FastMM 仅实例化一次。
没有版本控制问题。当您更新 FastMM(一旦使用,它就成为整个应用程序和插件的关键组成部分)时,您不必再次发布整个构建(应用程序和插件)。再次强调,更新共享包就足够了。
卸载插件时没有内存管理器问题。当第一个插件库被卸载后,我遇到了一些 FastMM 被卸载的问题,从而导致应用程序关闭时出现大量错误。
无跟踪问题 - 如果发生任何内存泄漏或其他内存问题,即使错误发生在 DLL 代码中,您也会获得有效的调用堆栈。
以下是我在 FastMM4Options.inc 中使用的(非标准)选项,以便使整个过程如上所述工作。
{$定义永不卸载}
{$定义UseRuntimePackages}
{.$define ShareMM}
好吧,我相信其余部分保持不变,但如果有问题,这里是完整的文件:
http://pastebin.4programmers.net/693
since "Everyone is sharing a single runtime package." I'd recommend the method I'm using. Simply, add FastMM4 to your shared runtime package (Of course, you'll need to put FastMM4 in "using" declaration in each library and host application anyway).
This way has some advantages like:
simple method to switch FullDebugMode on/off [and other options of course]. No project recompilation is needed, recompiling the shared package only is enough to switch the FullDebugMode in the whole application (including dll's) as the FastMM is instanced only once.
no versioning problem. When you update FastMM (which, once used, becomes crucial component of the whole app and plugins) you don't have to ship the whole build (app & plugins) again. Once again, updating the shared package is enough.
no memory manager issues when unloading plugins. I've had some problems with FastMM being uninstalled once the first plugin library was unloaded, thus causing tons of bugs on application shutdown.
no tracking problems - in case of any memory leak or other memory issue you'll be provided with valid call stack, even if the bug occurred in the DLL code.
Here are the (non-standard) options I'm using in my FastMM4Options.inc in order to get the whole thing working as described above.
{$define NeverUninstall}
{$define UseRuntimePackages}
{.$define ShareMM}
well I believe the rest was left unchanged, but if something is wrong, here is the full file:
http://pastebin.4programmers.net/693
据我所知,有 sharemm,它是 fastmm 的一个版本,用于跨 DLL 边界共享。
Afaik there is sharemm, a version of fastmm to share over DLL bounderies.
如果您的应用程序是使用运行时包编译的,则无需执行任何其他操作,因为运行时包始终只使用一个内存管理器。您只需指定一次您选择的内存管理器,最好在主应用程序代码中将其作为使用列表中的第一个单元。所有其他运行时包不需要修改,它们将自动使用正确的内存管理器,无论该内存管理器是什么。
如果您的应用程序是在没有运行时包的情况下编译的,那么每个 dll 都有自己的内存管理器。默认情况下,它们都使用默认的内存管理器,如果我没记错的话,它是一个共享 MM,也就是说,您可以在 dll 之间传输字符串。如果您想用另一个共享的 MM 替换默认的 MM,则需要将新的内存管理器作为第一个单元包含在您想要协同工作的每个 dll 或 exe 的使用列表中。
不同之处在于,运行时包共享发生在包级别。即使不分享的MM也会分享。如果没有运行时包,每个 DLL 都使用单独的 MM,只有当这些单独的内存管理器合作时,您才能共享。
我的观点是,除非您的应用程序与 dll 交互非常紧密(请阅读:在 dll 中具有表单和组件),否则最好的方法根本不是依赖共享内存管理器,而是正确管理内存,跟踪谁创建了内存什么并删除实例化它们的同一库中的对象。这并不难。只需返回接口而不是对象,返回短字符串(固定长度)或将数据复制到提供的缓冲区而不是返回字符串,等等。不要返回调用者将释放的东西,不要接受被调用者必须释放的东西,这样你基本上就安全了。这不仅解决了所有可能的内存管理器问题,还允许您用任何语言编写 dll。
If your application is compiled with runtime packages, no additional actions are needed because runtime packages use only one memory manager, always. You just need to specify the memory manager of your choice once, preferably in the main application code as the first unit in the uses list. All the other runtime packages do not require modifications, they'll use the correct memory manager automatically, whatever that memory manager is.
If your app is compiled without runtime packages then every dll has its own memory manager. By default they all use their default memory managers, and if I'm not mistaken, it's a sharing MM, that is, you can transfer strings for example to and from dlls. If you want to replace the default MM with another sharing one, you'll need to include new memory manager as the first unit in the uses list in EVERY dll or exe you want to work together.
The difference is that with runtime packages sharing occurs at the package level. Even non-sharing MM will be shared. Without runtime packages every DLL uses a separate MM, and it's only when those separate memory managers cooperate that you get sharing.
My opinion is that unless your app interacts with dlls really closely (read: has forms and components in dlls), the best approach is not to rely on having sharing memory manager at all, but to manage your memory properly, keeping track of who creates what and deleting objects in the same library where you instantiated them. It's not hard. Just return interfaces instead of objects, return shortstrings (fixed-length) or copy the data into the provided buffer instead of returning strings, and so on. Do not return things that will be freed by the caller, don't accept things that the callee will have to free, and you'll be basically safe. Not only this solves all the possible memory manager problems, it also lets you write dlls in any language.
Ypu 有两种选择:继续使用在 FastMM 发行版中找到的 ShareMem 单元和 BorldMM.dll 替代品,或者修改两者可执行文件和 DLL 以包含 FastMM 内存管理器,方法是将单元放置为第一个。您还应该根据您的需要定制在 FastMM4Options.inc 中找到的一些 $DEFINE,它们在那里得到了很好的解释。 AFAIK 运行时包使用已安装的内存管理器。
Ypu have two choices: keep on using the ShareMem unit and the BorldMM.dll replacement you find in the FastMM distribution, or modify both the executable and DLLs to include the FastMM memory manager, by placing the unit as the first one. You should also tailor some of the $DEFINEs you find in FastMM4Options.inc to your needs, they are well explained there. AFAIK run-time packages use the installed memory manager.