如何在Delphi中找到导致AV的悬空接口

Bri*_*ost 11 delphi debugging interface access-violation

我有一个复杂的应用程序,我刚刚介绍了一些更改,添加了几个带接口的新类,并删除了其他一些.功能上它一切正常但我在类的Destroy过程之后得到了一个访问冲突:

"模块'xxxx.exe'中地址0040B984的访问冲突.读取地址80808088".

我知道这是在该类的'Finalize'代码中,如果我进入反汇编(Delphi 2010),我确实可以看到AV的重点.我看不出一个简单的方法来找出我的哪个变量触发了这个.在深入了解这个过程时是否有一个程序可以让我了解被引用的实例?

谢谢Brian

gab*_*abr 13

在大多数情况下,可以使用FastMM并使用条件定义FullDebugModeCatchUseOfFreedInterfaces编译应用程序来捕获此类错误.只需确保将FastMM4放在dpr的"使用"列表中的第一位.


Jer*_*ers 13

此错误看起来像您正在使用FastMM进行内存管理.该错误表示您正在引用已由FastMM清除的指针DebugFillDWord.

这意味着您正在使用引用已释放的对象的接口.
这也意味着您尚未启用CatchUseOfFreedInterfaces.

为了更改这些并进行调试,您无法使用Delphi附带的库存FastMM.
您需要下载FastMM(版本4.94).

下载后:

就像gabr已经提到的那样,在内部FastMM4Options.inc,确保你启用FullDebugModeCatchUseOfFreedInterfaces(禁用CheckUseOfFreedBlocksOnShutdown,但你现在对后者不感兴趣).
您可能也想要启用RawStackTraces; 这取决于您当前的堆栈跟踪是否足够好.

当你完成这些设置,然后通过调试运行与FastMM您的应用程序,并把一个断点在FastMM4单元内的这种方法:

procedure TFreedObject.InterfaceError;
Run Code Online (Sandbox Code Playgroud)

我稍微修改了我的FastMM4单元以获得更多上下文信息; 我可以与你分享(我已经将它邮寄给FastMM4团队,但它还没有包含在官方消息来源中).

我写了一篇关于使用FastMM进行调试的非常密集的博客文章,可能对你有帮助.
如果需要进一步说明,请在此处留言:-)

祝你好运,如果你需要进一步的指示,请告诉我们.

--jeroen

编辑:20100701 - 强调Brian评论中提到的位.


The*_*Fox 6

找到问题的步骤:

  1. 像Gabr建议的那样在fulldebugmode中使用FastMM(我认为你已经这样做了,看看808080模式).
  2. 在您的Destroy过程中将您在类中使用的所有接口显式设置为nil
  3. 在Destroy过程的开头放置一个断点
  4. 现在逐步完成你的Destroy程序,当你触摸悬空界面时,你将获得访问冲突,你将知道它是哪个界面.
  5. 在您没有问题地填满所有接口后仍然拥有AV时,请为父类执行步骤2 - 5.

我也有这些问题,上面的方法帮助我找到了它们.我的问题是由实现接口的TComponents引起的.假设您有ComponentA和ComponentB,ComponentB实现了一个接口.您将ComponentB(或其接口)分配给ComponentA并存储接口引用.现在ComponentB被破坏,但ComponentA不知道这一点.当您销毁ComponentA时,它会触发接口,调用_Release方法然后获得AV.

解决方案是使用TComponent.FreeNotification.当您收到ComponentB的免费通知时,您将在ComponentA中找不到该界面.我对您的代码一无所知,但如果您的问题类似,您也可以使用FreeNotifications.

编辑:添加了第5步