delphi 2009,弹出菜单导致EStackOverFlow

发布于 2024-10-31 20:25:13 字数 2545 浏览 3 评论 0原文

堆栈的一小部分

:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:0043797f TFont.SetData + $2F
:00437d92 TFont.SetStyle + $36
:004b9839 TCustomActionControl.CMFontChanged + $1D
:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:004378c5 TFont.Assign + $61
:004bf1f0 TThemedMenuItem.CalcBounds + $68
:004b9839 TCustomActionControl.CMFontChanged + $1D
:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:0043797f TFont.SetData + $2F
:00437d92 TFont.SetStyle + $36
:004b9839 TCustomActionControl.CMFontChanged + $1D
:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:004378c5 TFont.Assign + $61
:004bf1f0 TThemedMenuItem.CalcBounds + $68
:004b9839 TCustomActionControl.CMFontChanged + $1D
:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:0043797f TFont.SetData + $2F
:00437d92 TFont.SetStyle + $36
:004b9839 TCustomActionControl.CMFontChanged + $1D
:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:004378c5 TFont.Assign + $61
:004bf1f0 TThemedMenuItem.CalcBounds + $68
:004b9839 TCustomActionControl.CMFontChanged + $1D
:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:0043797f TFont.SetData + $2F
:00437d92 TFont.SetStyle + $36
:004b9839 TCustomActionControl.CMFontChanged + $1D
:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:004378c5 TFont.Assign + $61
:004bf1f0 TThemedMenuItem.CalcBounds + $68
:004b9839 TCustomActionControl.CMFontChanged + $1D
:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:0043797f TFont.SetData + $2F
:00437d92 TFont.SetStyle + $36
:004bb1d7 TCustomActionControl.CMTextChanged + $1F
:004801f1 TControl.WndProc + $2D5
:0047fe17 TControl.Perform + $27
:0047ded6 TControl.SetTextBuf + $22
:004ba9df TCustomActionControl.SetActionClient + $C7
:004b6aa7 TCustomActionBar.CreateControl + $D3
:004a8b6f TCustomActionMenuBar.CreateControl + $B
:004bdbee TCustomActionDockBar.CreateControls + $A
:00481779 TControl.WMContextMenu + $121

,它会一直持续下去......

我生成的最后执行的代码是更改菜单的标题之一。

更新: 我已经追踪了源代码,它兑现的行是

procedure TPopupActionBar.Popup(X, Y: Integer);
...
FPopupMenu.RecreateControls;//crash here
FPopupMenu.Popup(X, Y);

,但是下面的行有一个递归调用。 并抛出单元 actnPopup.pas, 我找不到递归调用的尾部。

它是一个现有的代码,可以在旧的 Delphi 版本下运行和编译良好。创建新的 ManuPop 并替换旧的 ManuPop 后,效果很好。然而,由于原版包含了更多功能,因此设计有所损失。

还是一无所知。

更多更新:更奇怪的是,当我在我的机器(编译机)上运行代码时,它崩溃并烧毁,而在另一台机器(用户机器)上,它运行着彩虹和蝴蝶。我不明白!

small piece of the stack

:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:0043797f TFont.SetData + $2F
:00437d92 TFont.SetStyle + $36
:004b9839 TCustomActionControl.CMFontChanged + $1D
:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:004378c5 TFont.Assign + $61
:004bf1f0 TThemedMenuItem.CalcBounds + $68
:004b9839 TCustomActionControl.CMFontChanged + $1D
:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:0043797f TFont.SetData + $2F
:00437d92 TFont.SetStyle + $36
:004b9839 TCustomActionControl.CMFontChanged + $1D
:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:004378c5 TFont.Assign + $61
:004bf1f0 TThemedMenuItem.CalcBounds + $68
:004b9839 TCustomActionControl.CMFontChanged + $1D
:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:0043797f TFont.SetData + $2F
:00437d92 TFont.SetStyle + $36
:004b9839 TCustomActionControl.CMFontChanged + $1D
:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:004378c5 TFont.Assign + $61
:004bf1f0 TThemedMenuItem.CalcBounds + $68
:004b9839 TCustomActionControl.CMFontChanged + $1D
:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:0043797f TFont.SetData + $2F
:00437d92 TFont.SetStyle + $36
:004b9839 TCustomActionControl.CMFontChanged + $1D
:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:004378c5 TFont.Assign + $61
:004bf1f0 TThemedMenuItem.CalcBounds + $68
:004b9839 TCustomActionControl.CMFontChanged + $1D
:0047fe17 TControl.Perform + $27
:0047eb54 TControl.FontChanged + $40
:0043797f TFont.SetData + $2F
:00437d92 TFont.SetStyle + $36
:004bb1d7 TCustomActionControl.CMTextChanged + $1F
:004801f1 TControl.WndProc + $2D5
:0047fe17 TControl.Perform + $27
:0047ded6 TControl.SetTextBuf + $22
:004ba9df TCustomActionControl.SetActionClient + $C7
:004b6aa7 TCustomActionBar.CreateControl + $D3
:004a8b6f TCustomActionMenuBar.CreateControl + $B
:004bdbee TCustomActionDockBar.CreateControls + $A
:00481779 TControl.WMContextMenu + $121

and it goes on and on ...

the last code executed that i generated was, changing one of the menu's captions.

UPDATE:
i have traced the source code and the line it cashed on is

procedure TPopupActionBar.Popup(X, Y: Integer);
...
FPopupMenu.RecreateControls;//crash here
FPopupMenu.Popup(X, Y);

however there is a recursive call the line below.
and going throw the unit actnPopup.pas,
i can't find the tail of the recursive call.

its an existing code that worked and compiled well under older Delphi version. After A new ManuPop was created , and replaced the old one, it works well. However, there is a loss in the design as the original had more features into it.

Still clueless.

more updates: something even more oddish, as i run the code on my machine(the compiling machine), it crash and burn, and on another machine(a user machine), it run with rainbows and butterflies. i don't get!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

坏尐絯℡ 2024-11-07 20:25:13

一般准则

这是一个递归问题。
从调用堆栈中注意到,每次都会发生完全相同的序列。
这意味着某些东西导致代码从自身进入方法 - 即使它是间接的。

:0047fe17 TControl.Perform + $27 
:0047eb54 TControl.FontChanged + $40 
:0043797f TFont.SetData + $2F 
:00437d92 TFont.SetStyle + $36 
:004b9839 TCustomActionControl.CMFontChanged + $1D 
:0047fe17 TControl.Perform + $27 
:0047eb54 TControl.FontChanged + $40 
:004378c5 TFont.Assign + $61 
:004bf1f0 TThemedMenuItem.CalcBounds + $68 
:004b9839 TCustomActionControl.CMFontChanged + $1D 

下面的简单代码说明了同一类问题:

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

通常,只需设置一个断点并找出该方法可重入的原因。通常这是因为:

  • 递归是有意的,但存在阻止达到终止条件的错误。
  • 或者递归是循环“触发”行为的无意副作用。即对象 B 响应对象 A 的变化而改变其状态,反之亦然。所以 A & 上的事件B 继续打电话给对方。
  • Windows 消息体系结构的使用不正确。请务必警惕 Application.ProcessMessages。这是一种非常危险的方法,因为它可能会导致从任务/进程的中间重新进入代码 - 而不是 Windows 消息循环的下一次迭代。

这个具体问题

当然,查看堆栈,这似乎是标准的 Delphi 代码递归调用自身。但 RAD 开发的危险之一是设置属性值是一种编写代码的形式 - 尽管看起来并非如此。
特定的属性值可能会导致某些代码的行为略有不同,从而触发递归。

不幸的是,没有足够的信息来提供最终的解决方案,但我可以提供一些要检查的建议:

  • 当然,使用 debug dcu 进行编译可能有助于找出问题。不要被潜在客户阅读 VCL 源代码吓倒 - 这实际上是最好的学习方法之一。
  • 您添加了任何操作控件吗?
  • 您是否使用任何第三方组件?
  • 弹出菜单当时可见与否有区别吗?
  • 我注意到正在调用 FontChanged 方法,但更改标题不应触发该方法。
  • 如果您正在使用任何与 PopupMenu 交互的其他组件,请尝试一次删除或禁用它们。
  • 尝试将属性重置回默认值。这可以通过以文本形式查看 dfm 来完成。您在 dfm 中看到的大多数属性值都是非默认值。只需删除该行即可将其重置回默认值。

如果您仍然遇到困难,

您可以提供一些附加信息来帮助解决:

  • 设置标题的示例代码,包括触发它的事件。
  • 弹出菜单
  • 和与菜单交互的任何操作控件的事件处理程序。
  • dfm 作为相关控件的文本。

General Guidelines

This is a recursion problem.
Notice from the call stack that the exact same sequence occurs each time.
This means that something is causing code to enter a method from itself - even if it is indirectly.

:0047fe17 TControl.Perform + $27 
:0047eb54 TControl.FontChanged + $40 
:0043797f TFont.SetData + $2F 
:00437d92 TFont.SetStyle + $36 
:004b9839 TCustomActionControl.CMFontChanged + $1D 
:0047fe17 TControl.Perform + $27 
:0047eb54 TControl.FontChanged + $40 
:004378c5 TFont.Assign + $61 
:004bf1f0 TThemedMenuItem.CalcBounds + $68 
:004b9839 TCustomActionControl.CMFontChanged + $1D 

The following simple code illustrates the same kind of problem:

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

In general, one would simply set a breakpoint and find out why the method is re-entrant. Usually this is because:

  • The recursion is intentional, but there is a bug preventing the terminating condition being reached.
  • Or the recursion is an unintentional side-effect of circular 'trigger' behaviour. I.e. Object B changes its state in response to a change in Object A, and vice versa. So the events on A & B keep calling each other.
  • Incorrect use of Windows Message Architecture. Be very wary of Application.ProcessMessages. It is a very dangerous method to use beause it can cause re-entry into code from the middle of a task/process - as opposed to the next iteration of the Windows Message Loop.

This Specific Problem

Of course looking the stack, this appears to be standard Delphi code recursively calling itself. But one of the dangers of RAD development is that setting property values is a form of writing code - even though it doesn't seem that way.
It is possible that a particular property value may cause some of the code to behave slightly differently, thereby triggering the recursion.

Unfortunately there isn't enough information for a difinitive solution, but I can offer suggestions of things to check:

  • Of course, compiling with debug dcu's might help to track down the problem. Don't be intimidated by the prospect reading VCL Source code - it's actually one of the best ways to learn.
  • Have you added any Action Controls?
  • Are you making use of any third party components?
  • Is there a difference between whether the Popup Menu is visible at the time or not?
  • I notice that the FontChanged method is being called, yet changing a caption should not trigger that.
  • If you are using any additional components that would interact with the PopupMenu, try deleting or disabling them one at a time.
  • Try resetting properties back to their default values. This can be done viewing the dfm as text. Most property values you see in the dfm will be the non-default value. Simply deleting the line will reset it back to default.

If You're Still Struggling

You can provide some additional information to help out:

  • Sample code that sets the caption, including the event that triggers it.
  • The event handlers for the Popup Menu
  • and any Action Controls that interact with the menu.
  • The dfm as text of the relevant controls.
凉墨 2024-11-07 20:25:13

出现此类问题的典型原因是事件处理程序执行了某些操作,从而触发了相同的事件处理程序。因此会出现无限递归并导致堆栈溢出。这很有可能是你的问题。

为了解决这个问题,我会回顾一下调用堆栈的底部,找到它开始重复的地方。那里应该有线索。

The typical cause for something like this is an event handler that performs some action that triggers the same event handler. Hence the infinite recursion and resulting stack overflow. There's a very high probability that's your problem.

To work it out, I'd look back right to the base of the call stack and find where it starts repeating itself. There should be clues there.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文