如何调试仅在应用程序关闭时发生的崩溃? (Delphi)

问题描述:

因此,在最近发生的一些变化之后,我们发现我们最早的应用程序有时会在关机时崩溃。这会以“运行时错误216”消息的形式或Windows错误报告中的消息显示应用程序已停止工作。该应用程序已经发出OutputDebugString-每一回合的消息和AFAICT我们自己的所有代码正确执行完成。所有的析构函数都被调用,就像所有的终结节和类的析构函数一样,其中没有一个引发任何异常。如何调试仅在应用程序关闭时发生的崩溃? (Delphi)

此外,MadExcept和FastMM4的完整调试模式似乎都没有什么可抱怨的(尽管这可能是一个错误的结论,因为即使在这些组件自己的最终代码运行之前崩溃也可能发生)。

那么,你会怎么做?你会从哪里开始?


这个问题应该是更多的一般方法这一类的问题,而不是针对我目前正面临着这样的特定实例,我特意留出的细节。随意问你是否认为它们可能与调试方法的选择有关,我将在稍后添加它们。

+4

有一个VCL错误,在关机时显示为AV。这与'所有者'形式的破坏有关。我通过在'Application.Run'之后明确关闭.dpr文件中的表单来解决这个问题。如果让'Application'为你完成关闭,则可能会出现陈旧引用的问题。 – 2011-03-03 13:54:48

+0

@David:这听起来很有趣。你有一个质量控制编号吗?但是,除了主窗体之外,我使用各自的父窗体作为所有者在代码中创建了所有窗体。你所说的问题是否也适用于这种情况? – 2011-03-03 13:59:54

+0

如果你依赖破坏应用程序来将其他所有东西都关闭,那么我正在讨论的错误可能适用。尝试在您的.dpr文件中放入一个'MainForm.Free'。我会看看QC编号。 – 2011-03-03 14:08:05

您可能会遇到指针问题。某些事件或方法试图在不再存在的对象上运行。

+0

是的,这就是“运行时错误216”或多或少所暗示的,但问题是如何去追踪这个问题呢? – 2011-03-03 13:27:43

+0

如果您可以可靠地重现它,那么您可以使用调试器(您需要调试DCU)来确定它发生的位置。不幸的是,我认为你可能会在它提出的点上有一个非常绝望的堆栈跟踪。 – 2011-03-03 13:56:27

+0

@David:这个问题的“可靠再现”仍然是一个问题:我认为它发生在大约60%的时间。而且我还没有能够确定工作会议和非工作会议之间的区别。我实际上已经认为我已经修复了这个问题几次,只是为了让它再次发生几个会话... – 2011-03-03 14:04:54

那么Runtime error 216是内存问题(Access violation),它看起来像你引用某个对象,在那个时间点不存在。

Emarcadero写道:使用该sysutils的类图最运行时错误例外,它允许您的应用程序来解决该错误不终止

应用

你尝试在定稿设置breackpoint Sysutils的一部分?

我会试一试Allocation/Memory Profiler,它不确定你会找到错误代码行,但这可能会显示你的代码中存在内存问题的部分内容。

您使用的是运行时软件包吗?我以前见过类似的问题。如果您跨包边界共享全局变量或接口,则必须确保在卸载该包之前,清除所有属于某个包的类的引用;否则他们会尝试将虚拟呼叫转换为不再有效的内存。

+0

哦,是的,不仅运行时包,而且COM-DLL(即插件)依赖于这些包(正如主机EXE一样)。不要问。我今天不会再这样做,但它已经运行了十多年了......尽管我会仔细检查一些全球单身人士的参考资料。这确实听起来很有希望...... – 2011-03-03 14:18:05

+2

“现在运行十多年了”已经发生了什么变化?这可能是我如何解决这个问题。 – 2011-03-03 14:43:46

+0

Touché! ;)这对于一个被接受的答案来说已经足够好了。 :-P – 2011-03-03 17:17:20

运行时错误216意味着您有Av(访问冲突)并且SysUtils已经停止将这些错误转换为异常。

首先尝试:使用调试DCU构建并查看引发错误的单元系统,在那里设置一个断点。希望你可以在调试器中捕获它并从那里开始工作。

你可能有一个内存错误(dangling指针,null引用等等,在已经完成的单元中使用s串常量),最好的诀窍是在sysutils完成后检查最终的结果。您可以通过构建WITH debug dcu's来完成此操作,将断点设置为sysutils中的终结点并开始逐步执​​行代码,直到发生错误。

“运行时错误216”来自Windows本身,而不是Delphi异常处理程序。我发现它是由在Delphi的异常处理程序启动之前执行的单元的初始化和结束化部分中运行的代码引起的。特别是。在Delphi应用程序终止后需要通过运行的终止代码卸载的COM对象将导致此错误和类似的错误。所以检查那些东西。

MNG

+3

不完全:在单元系统中查看:函数MapToRunError将NT错误代码STATUS_ACCESS_VIOLATION映射到ErrCode:= 216。 – 2011-03-03 20:40:26

+0

感谢您的评论 - 无论如何,这发生在默认Delphi应用程序异常处理程序初始化之前或之后。单元在Delphi应用程序启动之前基于uses子句加载,在应用程序终止后卸载 - 初始化和终止部分在单元加载和卸载时运行,因此在那里运行的代码不由Delphi应用程序异常处理程序处理。这就是为什么你得到一个神秘的'运行时错误216'或217,并没有异常消息'Eaccess违反.. @'等 – user643124 2011-03-04 14:17:21

+1

这是不正确的;在异常处理机制断开之后,216来自Delphi RTL。这是德尔福的方式告诉有一个AV。 216不是窗体。 – 2011-03-04 16:02:13

与其他人一样说:216是指AV后SysUtils单元被关闭。通常,SysUtils之后关闭的唯一东西(并且有机会升级AV) - 就是系统单元。具体来说:内存管理器

因此,关机时的运行时错误216通常意味着内存损坏应用程序中的错误。

这可以很容易解决 - 只需在内存管理器中启用完整调试模式或使用调试内存管理器。然而,有时候,它可能很难找到。但是您可以先从MM的调试模式开始。

请参阅this article