FastMM 和动态加载 DLL

发布于 2024-09-04 04:12:05 字数 385 浏览 4 评论 0原文

我有一个主机应用程序,它在启动时加载十几个库。我想从 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

白色秋天 2024-09-11 04:12:05

摘自 FastMM4options.inc 文件。

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

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

{允许共享内存管理器
主应用程序和 DLL 之间
也是用 FastMM 编译的。
这允许您传递动态数组
以及 DLL 函数的长字符串
前提是两者都被编译使用
快MM。共享只有在以下情况下才有效
应该共享的库
内存管理器是用
“AttemptToUseSharedMM”选项集。
请注意,如果主应用程序是
单线程,DLL 是
您必须设置的多线程
main 中的 IsMultiThread 变量
应用程序为true否则会崩溃
当发生线程争用时。笔记
静态链接的 DLL 文件是
在主程序之前初始化
应用程序,所以主要应用程序
很可能最终会静态共享
加载了 DLL 的内存管理器,但没有
反之亦然。 }

{.$定义 ShareMM}

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

{.$define ShareMMIfLibrary}

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

{.$定义AttemptToUseSharedMM}

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

{$定义
启用向后兼容MM共享}

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.

{-----------------------Memory Manager
Sharing
Options------------------------}

{Allow sharing of the memory manager
between a main application and DLLs
that were also compiled with FastMM.
This allows you to pass dynamic arrays
and long strings to DLL functions
provided both are compiled to use
FastMM. Sharing will only work if the
library that is supposed to share the
memory manager was compiled with the
"AttemptToUseSharedMM" option set.
Note that if the main application is
single threaded and the DLL is
multi-threaded that you have to set
the IsMultiThread variable in the main
application to true or it will crash
when a thread contention occurs. Note
that statically linked DLL files are
initialized before the main
application, so the main application
may well end up sharing a statically
loaded DLL's memory manager and not
the other way around. }

{.$define ShareMM}

{Allow sharing of the memory manager
by a DLL with other DLLs (or the main
application if this is a statically
loaded DLL) that were also compiled
with FastMM. Set this option with
care in dynamically loaded DLLs,
because if the DLL that is sharing
its MM is unloaded and any other DLL
is still sharing the MM then the
application will crash. This setting
is only relevant for DLL libraries
and requires ShareMM to also be set to
have any effect. Sharing will only
work if the library that is supposed
to share the memory manager was
compiled with the
"AttemptToUseSharedMM" option set.
Note that if DLLs are statically
linked then they will be initialized
before the main application and
then the DLL will in fact share its MM
with the main application. This
option has no effect unless ShareMM is
also set.}

{.$define ShareMMIfLibrary}

{Define this to attempt to share the
MM of the main application or other
loaded DLLs in the same process that
were compiled with ShareMM set. When
sharing a memory manager, memory
leaks caused by the sharer will not be
freed automatically. Take into
account that statically linked DLLs
are initialized before the main
application, so set the sharing
options accordingly.}

{.$define AttemptToUseSharedMM}

{Define this to enable backward
compatibility for the memory manager
sharing mechanism used by Delphi 2006
and 2007, as well as older FastMM
versions.}

{$define
EnableBackwardCompatibleMMSharing}

此生挚爱伱 2024-09-11 04:12:05

您正在寻找的内容称为 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.

纵情客 2024-09-11 04:12:05

因为“每个人都共享一个运行时包”。我推荐我正在使用的方法。只需将 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

丶情人眼里出诗心の 2024-09-11 04:12:05

据我所知,有 sharemm,它是 fastmm 的一个版本,用于跨 DLL 边界共享。

Afaik there is sharemm, a version of fastmm to share over DLL bounderies.

守不住的情 2024-09-11 04:12:05

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

如果您的应用程序是在没有运行时包的情况下编译的,那么每个 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.

猥琐帝 2024-09-11 04:12:05

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文