5

我需要一些建议来调试 Delphi XE2 应用程序中的崩溃。我自己从未见过崩溃——事实上它很少发生,并且不能按需重现。

我们确实有一组来自 MadExcept 的 10 个崩溃报告。这些表明主线程当时正在主窗体的列表视图中处理 WM_PAINT 消息。每种情况下的调用堆栈都没有显示对我自己代码的引用,只有 VCL 代码和 comctl32.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.Perform 之一,从那里每次路径都不同。最终它以 comctl32.dll、USER32.dll、GDI32.dll 或 TControl.WndProc 之一结束,并引发 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/终止。(感谢 Chris Thornton 的评论建议这一点。)我认为在关机期间发生异常的可能性是合理的。不幸的是,直到 2014 年我们才会发布新版本,并且有可能通过新诊断获取错误报告。

4

3 回答 3

1

First of all, to deBUG access violation errors you have to find variables (memory pointers) that are referencing areas not owned memory by your process.

Mostly non-initialized variables causes the problem.

So my suggestion would be to change the piece the following way

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;

I hope that this will show you which variable is not passed as expected.

My guess is for aItem.

于 2013-06-06T13:56:41.590 回答
1

这只是一个猜测,但也许您面临与我相同的问题(看起来相似)。
我的问题是在与创建它们不同的线程中破坏 WinAPI 窗口
在这种情况下,Windows 不会破坏窗口并返回错误,但某些 Delphi 组件会忽略该错误,因此您最终会得到WndProc 指向垃圾内存的挂起窗口(Delphi 在组件破坏时将释放它,但窗口将保留在后面)。
当此窗口尝试处理任何消息时,它将转到 WndProc(未定义)并导致带有 AV 的随机调用堆栈。

因此,请确保您在同一线程中创建和删除窗口(特别注意TTimer,它们也会创建窗口)

于 2013-06-10T07:29:32.343 回答
1

有趣的在这里阅读。也许类似的事情正在发生?检查 canvas <> nil 不会有什么坏处

程序空闲时访问冲突 - 不跟踪信息以追踪错误

于 2013-05-30T18:43:49.970 回答