【问题标题】:Is it possible that FastMM is wrongly reporting an access violation?FastMM 是否有可能错误地报告访问冲突?
【发布时间】:2011-03-21 19:31:22
【问题描述】:

我有一个复杂的应用程序,在正常编译时按预期工作,但在使用 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
  Œ  ­  .  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €

【问题讨论】:

  • 您说关闭表单时会发生这种情况。请记住,关闭表单的行为会因许多其他因素而有所不同:它是什么样的表单?模态/非模态? MDI/SDI?你用 CloseAction 做什么?对其中一些问题的回答可能会更容易为您提供帮助。
  • CallNextHookEx in last call stack 对我来说看起来很可疑。这是调用钩子链的一部分。看起来安装了一些钩子,它可能会在不适当的时间调用您的代码。当然,这可能只是误报。
  • 您的表单是否实现了任何接口?您对该表单有哪些通知、回调和链接?这种形式是否会在关闭时自行释放?

标签: delphi access-violation fastmm


【解决方案1】:

它不是在报告 AV;它创建一个虚假的 AV 异常,以使您的进程戛然而止,因为它所走的道路——访问已删除的对象——经常导致数据损坏,这甚至更糟。

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

【讨论】:

  • 感谢 cmets。有没有办法确定哪些钩子已经到位以及它们可能起源于哪里?我将 TForms 嵌入到 TScrollBox 中。删除嵌入的一种方法是单击表单本身的按钮。那是我遇到这个问题的时候。我应该使用 TForm 以外的东西吗?
  • @User:如果不看你的代码,我真的无法很好地回答这个问题。
  • 您可以说访问冲突并不是完全伪造的,将来您可能会在对释放的内存进行这种访问时遇到真正的访问冲突。 fastMM 只是让一些东西变得沉默、致命和不规则,更可预测和明显。它只是将概率 1.0E-09 事件提高到 1.0 概率。
【解决方案2】:

看不到您的代码有点棘手。但从堆栈跟踪来看,在我看来,您可能会在处理发往该对象的消息的过程中破坏 TAdvCustomShapeButton 实例。

开始检查的好地方应该是当前与TfrmWaitingList.OnTanWaitingListItem 事件挂钩的方法。

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

表单是如何关闭的?您可能需要考虑 Form.Release。

【讨论】:

  • 我已将代码更改为调用 Form.Release 而不是 Form.Free 并且在完全调试模式下 FastMM 不再在应用程序的其他区域的 TCustomForm.DoClose() 方法中给我一个 EAbstractError,并且在我在这里报告的特定情况下,该错误不再发生!谢谢 Mason...虽然我知道 Release 我通常只使用 Free。
【解决方案3】:

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

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

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


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

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

在我看来,这是 FastMM 的最佳功能之一,注意此警告将在未来为您省去痛苦。试图在现场追查这样的问题是非常困难的。使用 FastMM 提供的信息修复它通常很简单。

【讨论】:

  • 嗯,不返回系统的主要原因是它的memmanagers通常从系统中大块分配,然后自己进行suballoc。因此,除非释放的对象不是块中的最后一个,否则无法返回该块。大分配通常通过操作系统直接分配。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-24
  • 2018-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多