我们在Delphi XE中处理第三方组件线程代码的方式遇到了问题.我说第三方是因为我们的核心应用程序本身并没有实现任何多线程代码.我确定的是,如果我使用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(启动FastMM的初始实例并与主应用程序共享)的行为将导致问题,即使我没有调用该dll.我接下来要做的是修改主应用程序以启用动态加载该DLL(并因此强制将内存管理器安装到主应用程序中)并查看是否有所作为.
更新3:动态加载DLL具有与不加载它相同的效果......一切正常.
使用Delphi XE.
当尝试从DLL访问Delphi接口对象时,如果我尝试动态地而不是静态地执行它,则会失败.
dll中的接口单元实现了一个返回接口实例的函数.静态链接时,进入函数时结果为零,一切正常.当动态加载时,结果是非零的,所以当完成对结果的赋值时,IntFCopy代码将其视为非零,因此在赋值之前尝试释放它,这会引发异常.
任何见解将不胜感激.
DLL包括testinterfaceload_u并导出testInt:
library testinterfaceload;
uses
SimpleShareMem,
SysUtils,
Classes,
testinterfaceload_u in 'testinterfaceload_u.pas';
{$R *.res}
exports testInt;
begin
end.
Run Code Online (Sandbox Code Playgroud)
testinterfaceload_u是定义接口和简单类实现的单元:
unit testinterfaceload_u;
interface
type ITestInt = interface
procedure Test;
end;
{this function returns an instance of the interface}
function testInt : ITestInt; stdcall; export;
type
TTestInt = class(TInterfacedObject,ITestInt)
procedure Test;
end;
implementation
function testInt : ITestInt;
begin
//debugger shows result as non-nil ITestInt even before this assignment, when dynamic
result := TTestInt.Create;
end;
procedure TTestInt.Test;
var
i : …Run Code Online (Sandbox Code Playgroud)