5

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

3 回答 3

13

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

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

于 2011-03-21T19:40:04.570 回答
7

看不到你的代码有点棘手。但是从堆栈跟踪来看,在我看来,您可能正在销毁一个TAdvCustomShapeButton正在处理发往该对象的消息的实例。

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

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

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

于 2011-03-21T20:42:01.420 回答
3

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

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

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


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

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

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

于 2011-03-21T19:39:14.633 回答