事件处理期间的Delphi堆栈信息

时间:2015-02-16 23:07:56

标签: delphi events stack handler

调试事件时,我希望看到“完整”堆栈,特别是触发事件的实际事件或方法。

一个简单的例子是在表单上放置一个ComboBox,并编写一个onChange事件。 onChange事件将在用户更改comboBox时触发(显然),但也可以通过其他例程触发,例如,在启动时,formActivate将触发它。

如果我在comboBox的OnChange事件中放置断点,我将看不到触发堆栈。为什么会这样,如何在调试期间获得这个“其他”堆栈信息?

我知道我可以逐步完成活动,最终会让我回到触发代码,这不是我想要的。

谢谢!


我想我会张贴一张如何启用dcu的图片。请注意,FormCreate事件现在实际上出现在堆栈中。

这是两个不同堆栈轨迹的图像。断点在两者中完全相同,请注意在第二次启用调试dcu后,我从代码中获取堆栈信息(不仅仅是vcl / rtl)。
enter image description here

2 个答案:

答案 0 :(得分:2)

我怀疑你错过了堆栈跟踪中的RTL / VCL函数。要使它们显示,请在项目选项中启用调试DCU

答案 1 :(得分:0)

  

启用Debug DCU后,我在堆栈中看到了自己的代码。   具体来说,FormCreate处理程序仅在启用调试后出现   的DCU。我很惊讶。

请参阅this

基于帧的方法的堆栈帧

RTL和VCL单元在关闭“堆栈帧”选项的情况下编译。这意味着任何基于帧的方法都无法在RTL / VCL单元中找到短例程。

然而,这一事实也没有那么明显的后果。请考虑以下代码:

procedure TForm1.Button1Click(Sender: TObject);
begin
  TStringList.Create;
end;

此代码通过泄漏TStringList实例来创建简单的内存泄漏。跟踪工具将检测泄漏并为其构建调用堆栈。由于为您的项目启用了“堆栈帧”选项,Button1Click例程具有堆栈帧。可以预期基于帧的跟踪方法将发现对Button1Click的调用并将其添加到调用堆栈。

事实并非如此。

Button1Click的堆栈框架允许方法识别调用者(在本例中为:TControl.Click)。那是因为堆栈帧不包含有关例程本身的信息。它包含有关来电者的信息:返回地址。 Button1Click例程的返回地址将指向TControl.Click。

但是Button1Click怎么样?由于TStringList是来自RTL的类 - 它的编译没有“Stack Frames”选项。因此,构造函数没有堆栈帧(因为它是非常简单的代码,不需要堆栈帧)。因此,基于帧的跟踪方法无法识别Button1Click例程。