简体   繁体   English

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

[英]Delphi Stack Info during Event Handling

When debugging events I would like to see the "complete" stack, specifically the actual event or method that triggered an event. 在调试事件时,我希望看到“完整的”堆栈,特别是实际事件或触发事件的方法。

A simple example would be to drop a ComboBox on a form, and write an onChange event. 一个简单的示例是将ComboBox放到窗体上,并编写一个onChange事件。 The onChange event will trigger when a user changes the comboBox (obviously), but it can also get triggered via other routines, eg, at startup, the formActivate will trigger it. 当用户更改comboBox时,onChange事件将触发(很明显),但是它也可以通过其他例程触发,例如,在启动时,formActivate将触发它。

If I place a breakpoint in the OnChange event of the comboBox, I won't see the triggering stack. 如果在comboBox的OnChange事件中放置一个断点,则不会看到触发堆栈。 Why is this, and how can I get this "other" stack info during debugging? 为什么会这样,在调试过程中如何获得此“其他”堆栈信息?

I know I can step through the event and it will eventually bring me back to the triggering code, this is not what I am looking for. 我知道我可以逐步完成该事件,最终它将使我回到触发代码,这不是我想要的。

Thank you! 谢谢!


I thought I would post an image of how enabling dcu's worked. 我以为我会发布有关启用dcu的工作方式的图片。 Note that the FormCreate event actually appears in the stack now. 请注意,FormCreate事件实际上现在出现在堆栈中。

Here is an image of two different stack traces. 这是两个不同堆栈跟踪的图像。 Breakpoint is exactly the same in both, note that after enabling debug dcu's in the second, I get stack information from my code (not just vcl/rtl). 两者的断点完全相同,请注意,在第二次启用调试dcu之后,我从代码中获得了堆栈信息(不仅仅是vcl / rtl)。
在此处输入图片说明

I suspect that you are missing the RTL/VCL functions from the stack trace. 我怀疑您在堆栈跟踪中缺少RTL / VCL函数。 To make them show up, enabled Debug DCUs in the project options. 要显示它们,请在项目选项中启用“ 调试DCU ”。

After enabling Debug DCU's, I saw my own code in the stack. 启用Debug DCU后,我在堆栈中看到了自己的代码。 Specifically the FormCreate handler only appeared after enabling debug dcus. 具体来说,仅在启用调试dcus之后才出现FormCreate处理程序。 I was surprised by this. 我对此感到惊讶。

See this : 看到这个

Stack frames for frame-based methods 堆叠框架以用于基于框架的方法

RTL and VCL units are compiled with "Stack Frames" option turned off. RTL和VCL单元在“堆栈框架”选项关闭的情况下进行编译。 This means that any frame-based method will not be able to find short routines in RTL/VCL units. 这意味着任何基于帧的方法都将无法在RTL / VCL单元中找到简短的例程。

However, this fact also have less obvious consequence. 但是,这一事实也没有那么明显的后果。 Consider this code: 考虑以下代码:

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

This code creates a simple memory leak by leaking instance of TStringList. 这段代码通过泄漏TStringList实例创建了一个简单的内存泄漏。 A tracing tool will detect a leak and build call stack for it. 跟踪工具将检测到泄漏并为其建立调用堆栈。 Button1Click routine has stack frame due to "Stack Frames" option being enabled for your project. 由于为项目启用了“堆栈框架”选项,因此Button1Click例程具有堆栈框架。 One may expect that frame-based tracing method will discover a call to Button1Click and add it to the call stack. 可能希望基于帧的跟踪方法将发现对Button1Click的调用并将其添加到调用堆栈中。

This is not so. 事实并非如此。

The stack frame for Button1Click allows method to identify the caller (in this case: TControl.Click). Button1Click的堆栈框架允许方法标识调用方 (在这种情况下:TControl.Click)。 That's because stack frame does not contain information about routine itself . 这是因为堆栈帧不包含有关例程本身的信息。 It contains information about the caller : return address . 它包含有关呼叫者的信息: 返回地址 Return address for Button1Click routine will point to TControl.Click. Button1Click例程的返回地址将指向TControl.Click。

But what about Button1Click? 但是,Button1Click呢? Since TStringList is a class from RTL - it's compiled without "Stack Frames" option. 由于TStringList是RTL中的一个类-它的编译没有“ Stack Frames”选项。 Thus, constructor does not have stack frame (because it's very simple code and do not require stack frame). 因此,构造函数没有堆栈框架(因为它是非常简单的代码,不需要堆栈框架)。 Therefore, it's not possible for frame-based tracing method to identify Button1Click routine. 因此,基于帧的跟踪方法无法识别Button1Click例程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM