gpt4 book ai didi

delphi - 在Delphi中检测VMT或堆损坏的正确工具是什么?

转载 作者:行者123 更新时间:2023-12-03 15:03:43 25 4
gpt4 key购买 nike

我是使用Delphi 2007开发大型应用程序的团队的成员,我们怀疑堆损坏,因为有时存在奇怪的错误,没有其他解释。
我相信编译器的Rangechecking选项仅适用于数组。我想要一个在未由应用程序分配的内存地址上进行写操作时给出异常或记录的工具。

问候

编辑:错误的类型:

错误:模块'BoatLogisticsAMCAttracsServer.exe'中地址00404E78的访问冲突。读取地址FFFFFFDD

EDIT2:感谢所有建议。不幸的是,我认为解决方案比这更深入。由于我们拥有源代码,因此我们为Delphi使用了Bold的修补版本。粗体框架可能会引入一些错误。是的,我们有一个包含由JCL处理的调用栈的日志,并且还跟踪消息。因此具有异常的调用栈可以像这样锁定:

20091210 16:02:29 (2356) [EXCEPTION] Raised EBold: Failed to derive ServerSession.mayDropSession: Boolean
OCL expression: not active and not idle and timeout and (ApplicationKernel.allinstances->first.CurrentSession <> self)
Error: Access violation at address 00404E78 in module 'BoatLogisticsAMCAttracsServer.exe'. Read of address FFFFFFDD. At Location BoldSystem.TBoldMember.CalculateDerivedMemberWithExpression (BoldSystem.pas:4016)

Inner Exception Raised EBold: Failed to derive ServerSession.mayDropSession: Boolean
OCL expression: not active and not idle and timeout and (ApplicationKernel.allinstances->first.CurrentSession <> self)
Error: Access violation at address 00404E78 in module 'BoatLogisticsAMCAttracsServer.exe'. Read of address FFFFFFDD. At Location BoldSystem.TBoldMember.CalculateDerivedMemberWithExpression (BoldSystem.pas:4016)
Inner Exception Call Stack:
[00] System.TObject.InheritsFrom (sys\system.pas:9237)

Call Stack:
[00] BoldSystem.TBoldMember.CalculateDerivedMemberWithExpression (BoldSystem.pas:4016)
[01] BoldSystem.TBoldMember.DeriveMember (BoldSystem.pas:3846)
[02] BoldSystem.TBoldMemberDeriver.DoDeriveAndSubscribe (BoldSystem.pas:7491)
[03] BoldDeriver.TBoldAbstractDeriver.DeriveAndSubscribe (BoldDeriver.pas:180)
[04] BoldDeriver.TBoldAbstractDeriver.SetDeriverState (BoldDeriver.pas:262)
[05] BoldDeriver.TBoldAbstractDeriver.Derive (BoldDeriver.pas:117)
[06] BoldDeriver.TBoldAbstractDeriver.EnsureCurrent (BoldDeriver.pas:196)
[07] BoldSystem.TBoldMember.EnsureContentsCurrent (BoldSystem.pas:4245)
[08] BoldSystem.TBoldAttribute.EnsureNotNull (BoldSystem.pas:4813)
[09] BoldAttributes.TBABoolean.GetAsBoolean (BoldAttributes.pas:3069)
[10] BusinessClasses.TLogonSession._GetMayDropSession (code\BusinessClasses.pas:31854)
[11] DMAttracsTimers.TAttracsTimerDataModule.RemoveDanglingLogonSessions (code\DMAttracsTimers.pas:237)
[12] DMAttracsTimers.TAttracsTimerDataModule.UpdateServerTimeOnTimerTrig (code\DMAttracsTimers.pas:482)
[13] DMAttracsTimers.TAttracsTimerDataModule.TimerKernelWork (code\DMAttracsTimers.pas:551)
[14] DMAttracsTimers.TAttracsTimerDataModule.AttracsTimerTimer (code\DMAttracsTimers.pas:600)
[15] ExtCtrls.TTimer.Timer (ExtCtrls.pas:2281)
[16] Classes.StdWndProc (common\Classes.pas:11583)


内部异常部分是重新引发异常时的调用堆栈。

编辑3:现在的理论是虚拟内存表(VMT)有所损坏。当发生这种情况时,没有任何迹象表明。仅当调用方法时,才会引发异常(总是在地址FFFFFFDD上,十进制为-35),但为时已晚。您不知道错误的真正原因。任何有关如何捕获这样的错误的提示都非常感谢!!!我们已经使用SafeMM进行了尝试,但是问题是,即使使用了3 GB标志,内存消耗仍然过高。所以现在我尝试向SO社区提供赏金:)

EDIT4:一个提示是,根据日志,在此之前通常(甚至总是)有另一个异常。例如,它可以是数据库中的乐观锁定。我们试图强行提出异常,但在测试环境中它可以正常工作。

EDIT5:故事仍在继续...我现在对过去30天的日志进行了搜索。结果:


“读取地址FFFFFFDB” 0
“读取地址FFFFFFDC” 24
“读取地址FFFFFFDD” 270
“读取地址FFFFFFDE” 22
“读取地址FFFFFFDF” 7
“读取地址FFFFFFE0” 20
“读取地址FFFFFFE1” 0


因此,目前的理论是,枚举(粗体字很多)会覆盖指针。我在上面的其他地址获得了5次点击。这可能意味着该枚举拥有5个值,其中第二个最常用。如果存在异常,则应该对数据库进行回滚,并且应该销毁Boldobjects。也许有可能不是所有东西都被破坏了,枚举仍然可以写入地址位置。如果是这样,也许可以通过regexpr在代码中搜索具有5个值的枚举?

EDIT6:总而言之,尚无解决方案。我意识到我可能会在调用堆栈上误导您。是的,其中有一个计时器,但是还有其他没有计时器的调用栈。抱歉但是有两个共同因素。


读取地址FFFFFFxx的异常。
调用堆栈的顶部是System.TObject.InheritsFrom(sys \ system.pas:9237)


这使我确信 VilleK最能说明问题。
我也确信问题出在Bold框架中。
但是大的问题是,如何解决这样的问题?
VilleK这样的Assert提示是不够的,因为损坏已经发生并且此时调用堆栈已消失。因此,请描述我对可能导致错误的原因的看法:


在某处为指针分配了错误的值1,但它也可以是0、2、3等。
将一个对象分配给该指针。
对象基类中有方法调用。这将导致方法TObject.InheritsForm被调用,并且在地址FFFFFFDD上出现异常。


这三个事件可以在代码中一起使用,但也可以在以后使用。我认为这对于最后一个方法调用是正确的。

EDIT7:我们与Bold Jan Norden的作者紧密合作,他最近在Bold框架的OCL评估器中发现了一个错误。解决此问题后,这类异常的发生率大大降低,但偶尔仍会出现。但这几乎解决了,这是一个很大的安慰。

最佳答案

我没有解决方案,但是有关该特定错误消息有一些线索。

System.TObject.InheritsFrom从Self-pointer(类)中减去常量vmtParent以获得指向父类地址的指针。

在Delphi 2007中,定义了vmtParent:

vmtParent = -36;

因此,在这种情况下,错误$ FFFFFFDD(-35)听起来像类指针为1。

这是一个重现它的测试用例:

procedure TForm1.FormCreate(Sender: TObject);
var
I : integer;
O : tobject;
begin
I := 1;
O := @I;
O.InheritsFrom(TObject);
end;


我已经在Delphi 2010中进行了尝试,并获得了“读取地址FFFFFFD1”的信息,因为vmtParent在Delphi版本之间是不同的。

问题在于,这种情况发生在Bold框架的深处,因此您可能难以在应用程序代码中防范它。

您可以对DMAttracsTimers代码(我假设是您的应用程序代码)中使用的对象进行尝试:

Assert(Integer(Obj.ClassType)<>1,'Corrupt vmt');

关于delphi - 在Delphi中检测VMT或堆损坏的正确工具是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1879806/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com