在Delphi中,检测VMT或堆损坏的正确工具是什么?
我是一个团队的成员,该团队将Delphi2007用于更大的应用程序,我们怀疑堆损坏,因为有时会出现奇怪的bug,没有其他解释。 我相信编译器的Rangechecking选项只适用于数组。我想要一个工具,当应用程序没有分配内存地址时,它会给出一个异常或日志 问候 编辑:错误类型为: 错误:模块“boatlogicsamcattracsserver.exe”中地址00404E78处存在访问冲突。读取地址ffffdd EDIT2:谢谢你的建议。不幸的是,我认为解决办法比这更深。我们使用了一个补丁版本的Bold for Delphi,因为我们拥有这个源代码。粗体框架中可能引入了一些错误。是的,我们有一个日志,其中包含由JCL处理的调用堆栈以及跟踪消息。因此,带有异常的调用堆栈可以如下锁定:在Delphi中,检测VMT或堆损坏的正确工具是什么?,delphi,heap,memory-corruption,vmt,bold-delphi,Delphi,Heap,Memory Corruption,Vmt,Bold Delphi,我是一个团队的成员,该团队将Delphi2007用于更大的应用程序,我们怀疑堆损坏,因为有时会出现奇怪的bug,没有其他解释。 我相信编译器的Rangechecking选项只适用于数组。我想要一个工具,当应用程序没有分配内存地址时,它会给出一个异常或日志 问候 编辑:错误类型为: 错误:模块“boatlogicsamcattracsserver.exe”中地址00404E78处存在访问冲突。读取地址ffffdd EDIT2:谢谢你的建议。不幸的是,我认为解决办法比这更深。我们使用了一个补丁版本的
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)
20091210 16:02:29(2356)[异常]引发的EBold:未能派生ServerSession.mayDropSession:布尔值
OCL表达式:非活动、非空闲和超时(ApplicationKernel.allinstances->first.CurrentSession self)
错误:模块“boatlogicsamcattracsserver.exe”中地址00404E78处存在访问冲突。读取地址ffffdd。位于位置BoldSystem.TBoldMember.CalculatedDriveMemberWithExpression(BoldSystem.pas:4016)
引发内部异常EBold:未能派生ServerSession.mayDropSession:布尔值
OCL表达式:非活动、非空闲和超时(ApplicationKernel.allinstances->first.CurrentSession self)
错误:模块“boatlogicsamcattracsserver.exe”中地址00404E78处存在访问冲突。读取地址ffffdd。位于位置BoldSystem.TBoldMember.CalculatedDriveMemberWithExpression(BoldSystem.pas:4016)
内部异常调用堆栈:
[00]System.TObject.InheritsFrom(sys\System.pas:9237)
调用堆栈:
[00]BoldSystem.TBoldMember.CalculatedDrivedMemberWithExpression(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.setDeriversState(BoldDeriver.pas:262)
[05]BoldDeriver.TBoldAbstractDeriver.deriver(BoldDeriver.pas:117)
[06]BoldDeriver.TBoldAbstractDeriver.com(BoldDeriver.pas:196)
[07]BoldSystem.TBoldMember.EnsureContentsCurrent(BoldSystem.pas:4245)
[08]BoldSystem.TBoldAttribute.EnsureRenotnull(BoldSystem.pas:4813)
[09]BoldAttributes.TBABoolean.GetAsBoolean(BoldAttributes.pas:3069)
[10] BusinessClasses.TLogonSession.\u GetMayDropSession(code\BusinessClasses.pas:31854)
[11] DMAttracsTimers.TAttracsTimerDataModule.RemoveDanglingLogonSessions(代码\DMAttracsTimers.pas:237)
[12] DMAttracsTimers.TAttracsTimerDataModule.UpdateServerTimeOnTimerRig(代码\DMAttracsTimers.pas:482)
[13] DMAttracsTimers.TAttracsTimerDataModule.TimerKernelWork(代码\DMAttracsTimers.pas:551)
[14] DMAttracsTimers.TAttracsTimerDataModule.AttracStimerTime(代码\DMAttracsTimers.pas:600)
[15] ExtCtrls.TTimer.Timer(ExtCtrls.pas:2281)
[16] Classes.StdWndProc(公共\Classes.pas:11583)
内部异常部分是重新调用异常时的调用堆栈
EDIT3:目前的理论是虚拟内存表(VMT)不知何故被破坏了。当这种情况发生时,没有迹象表明会发生。只有在调用方法时才会引发异常(始终在地址ffffff dd,-35十进制上),但随后就太迟了。你不知道错误的真正原因。任何关于如何捕捉这样一个bug的提示都是非常感谢的!!!我们已经尝试使用SafeMM,但问题是即使使用3 GB标志,内存消耗也太高。所以现在我试着给So社区一个赏金:)
EDIT4:一个提示是,根据日志,在此之前通常(甚至总是)存在另一个异常。例如,它可以是数据库中的乐观锁定。我们曾试图通过强制方式引发异常,但在测试环境中,它运行良好
EDIT5:故事继续。。。我搜索了过去30天的日志。结果是:
- “读取地址FFFFFF DB”0
- “读取地址FFFFFF DC”24
- “读取地址FFFFFF DD”270
- “读取地址FFFFFF DE”22
- “读取地址FFFFFF DF”7
- “读取地址FFFFFF E0”20
- “读取地址FFFFFF E1”0
- 读取地址FFFFFF XX时发生异常李>
- 调用堆栈的顶部是System.ToObject.InheritsFrom(sys\System.pas:9237)
procedure TForm1.FormCreate(Sender: TObject);
var
I : integer;
O : tobject;
begin
I := 1;
O := @I;
O.InheritsFrom(TObject);
end;
Assert(Integer(Obj.ClassType)<>1,'Corrupt vmt');
procedure TAttracsTimerDataModule.AttracsTimerTimer(ASender: TObject);
begin
if FInTimer then
begin
// Let us know there is a problem or log it to a file, or something.
// Even throw an exception
OutputDebugString('Timer called re-entrantly!');
Exit; //======>
end;
FInTimer := True;
try
// method contents
finally
FInTimer := False;
end;
end;
procedure TForm11.Button1Click(Sender: TObject);
var
c: TComponent;
i: Integer;
p: pointer;
begin
//create
c := TComponent.Create(nil);
//get size and memory
i := c.InstanceSize;
p := Pointer(c);
//destroy component
c.Free;
//this call will succeed, object is gone, but memory still "valid"
c.InheritsFrom(TObject);
//overwrite memory
FillChar(p, i, 1);
//CRASH!
c.InheritsFrom(TObject);
end;