我需要一些调试Delphi XE2应用程序崩溃的建议。我自己从未见过崩盘——事实上,这种情况很少发生,而且不能按需重现。
我们确实有一组来自MadExcept的10个崩溃报告。这些显示主线程当时正在主表单的列表视图中处理WM_PAINT消息。每种情况下的调用堆栈都没有显示对我自己代码的引用,只是VCL代码和comcomtl32 .dll, ntdll.dll和USER32.dll中的函数。
列表视图的问题是TColorListView,它派生自TCustomListView,并处理OnCustomDrawItem和OnDeletion事件。但正如我所说,当崩溃发生时,我的TColorListView代码都不在调用堆栈上。
每种情况下崩溃的实际位置各不相同,但导致崩溃的调用顺序(从早到晚)始终是:
KiUserCallbackDispatcher
RtlAnsiStringToUnicodeString
StdWndProc
TWinControl.MainWndProc
TCustomListView.WndProc
TWinControl.WndProc
TControl.WndProc
TCustomListView.WMPaint
TWinControl.WMPaint
TWinControl.WMPaint
TWinControl.DefaultHandler
CallWindowProcA
TControl.WndProc
之后它进入StdWndProc/SendMessageW/TControl之一。执行,从那里出发的路径每次都不同。最终它会出现在comtl32 .dll、USER32.dll、GDI32.dll或TControl中。并引发一个EAccessViolation。遗憾的是,我没有关于用户当时试图做什么的信息,因为用户没有填写错误报告的那一部分。
你能建议任何"通灵调试"技术,我可以用它来确定这个崩溃的原因(从而修复它)?
更新以回答下面评论中的问题:
procedure TColorListView.HandleCustomDrawItem(aSender: TCustomListView; aItem: TListItem;
aState: TCustomDrawState; var aDefaultDraw: Boolean);
begin
Canvas.Font.Color := ItemColors[aItem.Index];
end;
在(仅仅)一个崩溃报告中,它似乎进入了TListItem。GetIndex并进一步崩溃几个堆栈帧。不过,这可能是一个转移注意力的话题。
"执行"消息是什么?对不起,我不知道。MadExcept没有给我方法参数值;只有方法名。
5月31日
虽然我更喜欢从我所拥有的信息中找到错误,但我也欢迎对我可以添加到程序中的任何新诊断的建议,以便在下一个版本之后再次发生这种崩溃,我将有更多的事情要做。我很困惑,因为在崩溃的时候,我可以修改的代码甚至都没有在调用堆栈上。
6月13日
我已经在MadExcept报告中添加了一行,告诉我异常发生时应用程序处于什么状态-启动/活动/空闲/ModalDlg/终止。(感谢克里斯·桑顿的评论。)我认为异常很有可能是在关机期间发生的。不幸的是,要到2014年我们才会发布新版本,并且有可能得到带有新诊断的bug报告。
这只是一个猜测,但也许你面临着同样的问题,我有(看起来相似)。
我的问题是在销毁WinAPI窗口在不同的线程比他们创建。
在这种情况下,Windows不会销毁窗口并返回错误,但是一些Delphi组件只是忽略该错误,所以你最终会挂起窗口,其中有WndProc指向垃圾内存(它将被Delphi在组件销毁时释放,但窗口将留在后面)。当这个窗口将尝试处理任何消息时,它将转到windowproc(这是未定义的)并导致随机调用AV堆栈。
所以确保你是在同一个线程中创建和删除窗口(特别注意TTimer,它们也创建窗口)
这里读起来很有趣。也许正在发生类似的事情?检查canvas <> nil也无妨
程序空闲时访问冲突-没有跟踪信息来跟踪错误
首先,要调试访问冲突错误,您必须找到引用进程不拥有内存的区域的变量(内存指针)。
大多数未初始化的变量会导致问题。
所以我的建议是这样修改
procedure TColorListView.HandleCustomDrawItem(aSender: TCustomListView; aItem: TListItem;
aState: TCustomDrawState; var aDefaultDraw: boolean);
begin
if Canvas = nil then
.... ; // a breakpoint here
if ItemColors = nil then
.... ; // a breakpoint here
if aItem = nil then
.... ; // a breakpoint here
Canvas.Font.Color := ItemColors[aItem.Index];
end;
我希望这将告诉您哪个变量没有按预期传递。
我猜是aItem。