3

我们在 Delphi XE 中处理 3rd-party 组件线程代码的方式一直遇到问题。我说 3rd-party 是因为我们的核心应用程序本身并没有实现任何多线程代码。我确定的是,如果我使用 SimpleShareMem(我们有几个与主应用程序共享字符串数据的 dll)会发生奇怪的内存损坏,但如果我安装 FastMM4 单元,这些错误就会消失。奇怪的是,我的意思是错误很少连续两次相同,尽管它们在同一个大范围内。我最初安装 FastMM4 是为了尝试确定错误的原因,但实际上它们在安装时根本不会发生。我在选项集中设置了条件,允许我在 SimpleShareMem 和 FastMM 之间来回翻转项目组中的所有模块,

我的直接例子是 TRichView。我发现当我使用 hunspell 拼写检查器时,我可以通过同时粘贴和单击向上滚动很多次来在 PaintBuffered/PaintTo 过程中或附近产生错误(这取决于我需要多少次这样做会产生错误)。有时它是一个外部异常,它解决了一个浮出水面的异常,有时我在异常处理代码中遇到堆栈溢出。

我遇到的另一个例子是 AnyDAC (DA-SOFT) 远程/文件监控系统,它也在一个单独的线程中运行,它不能与 SimpleShareMem 一起使用,但与 FastMM4 一起工作正常。

基于这些经验,我不得不使用 FastMM4 单元进行生产构建,这对我来说可能看起来很奇怪。当然,我总是首先怀疑我自己的代码,所以我想知道是否有什么我可以做的事情来加剧这个问题,尽管 FastMM4 并没有显示主应用程序有任何堆栈损坏等。

所以,我的问题是,谁能想到为什么 FastMM4 比 Delphi XE 使用的任何版本的 FastMM 更适合多线程操作的原因?

更新:我想补充一点,我现在已经使用旧的 Sharemem/borlndmm.dll 概念进行了一些测试,而且效果也很好。

更新 2:感谢您的建议。我一直试图找到导致我的问题的 heisenbug,但收效甚微。我确实有一个额外的观察。

如果我修改主应用程序使其不加载需要 ShareMem 的 DLL,那么无论我使用何种内存管理器,AnyDAC 日志记录或 TRichView 都没有问题。即使我没有调用该 dll,加载该 DLL(它启动 FastMM 的初始实例并与主应用程序共享)的行为也会导致问题。我要做的下一件事是修改主应用程序以启用该 dll 的动态加载(从而强制将内存管理器安装到主应用程序中)并查看是否有所不同。

更新 3:动态加载 dll 与不加载它的效果相同......一切正常。

4

1 回答 1

5

Delphi XE 中嵌入的内存管理器是 FastMM4 的精简版。

内存块分配器本身是相同的,但共享机制不一样。

默认情况下,在 中设置以下条件FastMM4Options.inc

{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}

它将为库创建一个隐藏的窗口句柄来检索共享内存管理器实例——这就是它在 Delphi 2006 和 2007 中的工作方式。

自 Delphi 2009 以来实现的 FastMM4 的缩减版本中不再存在这种共享GetMem.inc- 它仅实现共享内存管理器文件映射(这是新方法)。其中一个库可能需要旧版本的内存管理器共享,无法找到共享内存管理器实例,因此使用它自己的内存分配器 - 并且无法处理共享内存(如string实例)。

这是我在两个版本之间发现的唯一区别,这可能是共享在您的程序中无法按预期工作的原因。您可能有一些使用 Delphi 2006 或 2007 编译的库,并且共享方法已被 Embarcadero 弃用(为了节省一些代码字节?)。

于 2011-11-04T17:54:32.833 回答