Delphi FastMM是否有可能错误地报告访问违规?

Delphi FastMM是否有可能错误地报告访问违规?,delphi,access-violation,fastmm,Delphi,Access Violation,Fastmm,我有一个复杂的应用程序,在正常编译时可以像预期的那样工作,但是在使用FastMM 4.97(最新版本)编译时关闭表单会产生访问冲突。AV发生在消息分派尝试处理一条消息时,该消息是针对表单上已被销毁的按钮的。我还为项目启用了Eurekalog 6.1.0.1(最新版本)。当在禁用FastMM的FullDebug模式的情况下执行相同的代码时,它不会捕获任何运行时异常 在某些情况下,FastMM是否可能改变EXE的行为,从而导致或错误报告访问冲突 以下是FastMM错误报告: ------------

我有一个复杂的应用程序,在正常编译时可以像预期的那样工作,但是在使用FastMM 4.97(最新版本)编译时关闭表单会产生访问冲突。AV发生在消息分派尝试处理一条消息时,该消息是针对表单上已被销毁的按钮的。我还为项目启用了Eurekalog 6.1.0.1(最新版本)。当在禁用FastMM的FullDebug模式的情况下执行相同的代码时,它不会捕获任何运行时异常

在某些情况下,FastMM是否可能改变EXE的行为,从而导致或错误报告访问冲突

以下是FastMM错误报告:

--------------------------------2011/3/21 13:30:17--------------------------------
FastMM has detected an attempt to call a virtual method on a freed object. An access violation will now be raised in order to abort the current operation.

Freed object class: TftGenericButton80

Virtual method: Offset +80

Virtual method address: 4A1FF0

The allocation number was: 5628628

The object was allocated by thread 0xE80, and the stack trace (return addresses) at the time was:
403110 [System][@GetMem]
404F03 [System][TObject.NewInstance]
42E85D [FastMM4][CreateComponent]
42EAD9 [FastMM4][TReader.ReadComponent]
42FEE1 [Classes][TReader.ReadValue]
42ED86 [FastMM4][TReader.ReadDataInner]
42ECC5 [FastMM4][TReader.ReadData]
433802 [Classes][TComponent.ReadState]
4A21CE [Controls][TControl.ReadState]
4A5742 [Controls][TWinControl.ReadState]
48BCA0 [Forms][TCustomForm.ReadState]

The object was subsequently freed by thread 0xE80, and the stack trace (return addresses) at the time was:
40313B [System][@FreeMem]
404F21 [System][TObject.FreeInstance]
405339 [System][@ClassDestroy]
8AFBEF [..\..\AdvShapeButton.pas][AdvShapeButton][TAdvCustomShapeButton.Destroy][1422]
4A5601 [Controls][TWinControl.Destroy]
48A9DD [Forms][TScrollingWinControl.Destroy]
48B9D8 [Forms][TCustomForm.Destroy]
48B9F2 [Forms][TCustomForm.Destroy]
404F67 [System][TObject.Free]
A9C42C [..\..\fmWaitingList.pas][fmWaitingList][TfrmWaitingList.OnTanWaitingListItem][130]
A9D41B [fmWaitingListItem.pas][fmWaitingListItem][TfrmWaitingListItem.DoOnTanItem][142]

The current thread ID is 0xE80, and the stack trace (return addresses) leading to this error is:
8B2630 [..\..\AdvShapeButton.pas][AdvShapeButton][TAdvCustomShapeButton.Click][3042]
4A4817 [Controls][TControl.WMLButtonUp]
4A4227 [Controls][TControl.WndProc]
7E42B401 [CallNextHookEx]
7E42B401 [CallNextHookEx]
7E42B372 [MoveWindow]
7E42B317 [MoveWindow]
7E42B326 [MoveWindow]
7E42B326 [MoveWindow]
7E4278D0 [GetWindowTextLengthW]
7E4278E0 [GetWindowTextLengthW]

Current memory dump of 256 bytes starting at pointer address 7FEB5F00:
90 8C AD 00 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
  Œ  ­  .  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €

我发现FastMM在这方面非常可靠

如果在释放模式下运行,99.9%的时间里调用释放对象上的方法不会有问题。0.1%的时间总是只发生在您最有价值的客户机器上

所以,我敢打赌这是个问题。事实上,这很容易追踪,因为FastMM提供了所有的调用堆栈,精确地显示了它是如何发生的。你只需要仔细地了解细节


现在,您可能会问,如何对已释放的对象调用方法?嗯,当您释放一个对象时,您将内存返回到内存管理器。但内存管理器通常会保留该内存,并等待适当的时机重新使用它。关键的是,它不会立即将其返回到系统,因为这样做很昂贵(需要花费大量时间)

这就是内存管理器快速运行的原因,但它也会导致错误,例如对被屏蔽的空闲对象调用方法。如果内存已返回到系统,那么这样的操作将导致真正的访问冲突。这就是我所说的大多数时候的意思,在内存管理器处于释放模式时,这样的错误不会出现


在我看来,这是FastMM最好的功能之一,注意这一警告将在将来为您省去痛苦。试图在实地查清这样一个问题是极其困难的。用FastMM提供的信息修复它通常很简单。

它没有报告AV;它创建了一个虚假的AV异常,以使您的进程突然停止,因为它所在的道路——访问一个已删除的对象——经常导致数据损坏,甚至更糟


问题不是访问违规;问题是有人试图调用已被释放的按钮上的
Click
方法。仅从这个堆栈跟踪来看,您或其他人似乎安装了一个钩子,该钩子包含对按钮的引用,并且在表单销毁后不会适当地更新自身。这就是我要开始寻找的地方。

在看不到代码的情况下有点棘手。但是从堆栈跟踪看来,在处理对象的消息中间,您可能正在破坏<代码> TAdvCustomShapeButton <代码>实例。

开始检查的好地方应该是当前连接到
TfrmWaitingList.OnTanWaitingListItem
事件的方法


您说过在关闭表单时会发生这种情况。
我假设您的表单在关闭时被销毁(而不是简单地隐藏),因此它会反过来销毁表单拥有的所有对象


表单是如何关闭的?你可能想考虑表单。但是,请释放。

谢谢你的评论。有没有办法确定什么钩子在适当的位置以及它们可能起源于何处?我正在将TForms嵌入到TScrollBox中。删除嵌入式for的一种方法是单击表单本身上的按钮。那就是我遇到这个问题的时候。我应该使用TForm以外的东西吗?@User:如果不看你的代码,我真的无法很好地回答这个问题。你可以说访问冲突并不是完全伪造的,将来你可能会在访问释放的内存时遇到真正的访问冲突。fastMM只是在制造一些无声的、致命的、不规则的东西,更容易预测,更明显。这只是将概率1.0E-09事件提高到1.0概率。您说过这是在关闭表单时发生的。请记住,关闭表单的行为会因其他因素的不同而有所不同:它是什么类型的表单?模态/非模态?MDI/SDI?你用CloseAction做什么?对其中一些问题的回答可能会使您更容易获得帮助。CallNextHookEx在最后一个调用堆栈中看起来非常可疑。这是呼叫胡克链的一部分。看起来好像安装了一些钩子,它可能会在不合适的时间调用您的代码。当然,这可能只是误报条目。您的表单是否实现了任何接口?您有哪些通知、回调和该表单的链接?该表单是否在关闭时释放自身?我已将代码更改为调用form.Release而不是form.free和FastMM,在完全调试模式下,在应用程序的其他区域中,TCustomForm.DoClose()方法不再为我提供EAbstractError,并且在我在此报告的特定情况下,该错误不再发生!谢谢Mason…当我意识到发布时,我通常只使用Free。好吧,不返回系统的主要原因是it MemManager通常以大的块从系统分配,然后再执行子分配本身。因此,除非解除分配的对象不是块中的最后一个对象,否则无法返回块。大型分配通常通过OS tho直接分配。