Delphi-跟踪传播访问冲突的工具/技术

Delphi-跟踪传播访问冲突的工具/技术,delphi,delphi-xe,Delphi,Delphi Xe,即使听起来很奇怪,我相信每个人在使用大量定制组件的大型应用程序时都会遇到这种问题。AV在某处生成,但应用程序仍在继续执行,稍后会引发错误。我不是说多线程应用程序。只是一般的单线程应用程序 我正在努力寻找随机引发的错误,甚至我正在使用madecept/AQT调试dcu和断点,但我无法找到引发错误的确切步骤,以及从何处引发错误。错误正在传播,有时会在TWinControl destroy(Delphi标准TPageControl)上引发,有时在打开数据集(以前使用相同的SQL多次打开和关闭)时引发。

即使听起来很奇怪,我相信每个人在使用大量定制组件的大型应用程序时都会遇到这种问题。AV在某处生成,但应用程序仍在继续执行,稍后会引发错误。我不是说多线程应用程序。只是一般的单线程应用程序

我正在努力寻找随机引发的错误,甚至我正在使用madecept/AQT调试dcu和断点,但我无法找到引发错误的确切步骤,以及从何处引发错误。错误正在传播,有时会在TWinControl destroy(Delphi标准TPageControl)上引发,有时在打开数据集(以前使用相同的SQL多次打开和关闭)时引发。所以堆栈被破坏了,我不能在这种情况下使用它


我知道这个问题太本地化了,但我想问你还有什么其他方法可以跟踪此类错误

我认为这是一个一般性问题,而不是德尔菲问题。但一些有用的技术包括:

  • 过多的日志记录到一个文件中,以便以后可以使用所有值对其进行研究
  • 到处都是断言。您可以禁用它们,以便它们在发布时不增加成本
  • 禁用部分应用程序,直到错误停止出现,或
  • 禁用除一些基本shell之外的所有功能,然后逐个启用组件,直到AVs返回
  • 使用
    ReportMemoryLeaksOnShutdown:=true跟踪内存泄漏

当您发现一个似乎触发错误的组件时,进入该组件并重复该过程,逐步禁用其中的所有内容并启用部分。

记录到文件可以更改结果,因此我建议使用GExperts调试器,它可以将消息实时写入输出窗口。编写一个包装器函数,以便您可以根据需要转储到文件,控制记录的内容(日志级别过滤器),等等

将日志记录放在所有单元的初始化/终结中。我发现“出乎意料”的错误经常发生在定稿过程中。例如:您关闭了一个数据库连接,但该对象已被其他对象释放。哦

还要将日志记录放在任何组件的事件处理程序中,以及这些组件的析构函数中。这将显示组件销毁后是否触发事件


作为最后的手段,您可能必须“消化”程序,以“块”的形式删除您编写的所有代码。将代码保存在某处,删除form1上的事件处理程序,编译并测试。如果错误消失,请放回事件处理程序并删除其中的一半,然后重新测试。继续,直到你把它缩小到足够小的范围,然后应该通过消除过程来识别罪魁祸首。

我将从使用其他一些内存管理器开始,看看你是否能够迫使应用程序的使用模式更快地崩溃

可以使用FullDebugMode运行(请确保将相应的DLL与应用程序EXE放在一起)。它可以做一些重要的事情:

  • 用模式填充内存(如建议的)
  • 释放块后检查对块的修改
  • 应用程序终止时记录内存泄漏
  • 对某些事件进行回调,以便您可以记录内容
过去我写过两篇关于FastMM的博客文章,我知道我应该写更多关于它和其他内存管理器的文章

编辑:关于SO用户的其他内存管理器的好文章

出于文档的目的,其他一些内存管理器(其中大多数不适用于您的情况,但我还没有找到一篇包含所有内存管理器的帖子):

在多线程环境中,这些可能很好:

  • (基于)
在EXE/DLL设置中,您可能需要尝试

在他的书中,安德烈·穆什做到了


注意:+1;好问题,我应该找些时间写一篇关于Delphi内存管理器的后续博文(:

两件事已经成为我最好的朋友,特别是在开发非可视化内容时,而不仅仅是在Delphi中:

  • 单元测试和日志记录
我使用(DUnit)进行单元测试,但也执行系统和压力测试。 我使用AQT来评估单元测试和内存泄漏检测的覆盖率。 我的想法是,我不需要预先为每个方法编写测试, 但是试着写一个尽可能多的测试。 当出现特定问题时,我编写一个测试来重现该问题 然后我就知道我的修正什么时候起作用了。 另一个优势是,对于大型应用程序,我可以在进行更改后运行测试 并确认一切仍按预期工作

我使用的另一个工具是SmartInspect,因为它记录进入和离开方法,
除此之外,它还有一个向导来检测现有代码(添加enter-leave-logging)还有一个用来过滤日志的控制台。

奇怪的是,没有人提到调试内存管理器SafeMM。它可以准确地捕捉AV发生的位置。

谢谢你的-1。现在,你能告诉我你在处理这种情况时使用过的工具吗?我只能给出一个建议,将日志添加到你的应用程序中。至少它可以提供e提示用户在AV发生之前正在做什么。(中性化-1)我尝试了使用日志,try/except/finally但没有成功。错误会随机传播和引发。可能是在free覆盖FreeMem后使用,这样它会使用固定模式(如$DEADBEEF)或第n个返回地址擦除内存区域(可能会提示它在何处被过早删除,但由于类继承的原因几乎不会。然后调用继承的FreeMem。希望这会将您的bug转变为早期死亡类别。另外,Windows DEP可能会有所帮助,禁用除真实代码段以外的任何代码执行。您是否也在