【问题标题】:Delphi JCL Debug missing stack frame entries for JDBGDelphi JCL Debug 缺少 JDBG 的堆栈帧条目
【发布时间】:2015-12-07 20:07:21
【问题描述】:

我使用以下代码在发生异常时转储堆栈帧:

...
var
  FTraceList: TStringList;
...
procedure TTraceForm.LogException(ExceptObj: TObject; ExceptAddr: Pointer; IsOS: Boolean);
begin
...
StackList := JclCreateStackList(false, 0, Caller(0, false));
try
  FTraceList.Add('');
  FTraceList.Add('Stack trace at the moment of the exception:');
  StackList.AddToStrings(FTraceList, true, true, true, true);
finally
  Stacklist.Free;
end;
end;

但它在 Debug 和 Release 模式下的行为不同。

对于在调试模式下编译时主窗体的 OnKeyDown 中的预期异常(用于测试目的的异常)(Delphi 调试信息),结果是:

Stack trace at the moment of the exception:
(00591276){Main.exe     } [00992276] DlgTraceException.TTraceForm.LogException (Line 162, "DlgTraceException.pas" + 55) + $4
(0058B8FF){Main.exe     } [0098C8FF] JclDebug.JclCreateStackList + $17
(00591281){Main.exe     } [00992281] DlgTraceException.TTraceForm.LogException (Line 162, "DlgTraceException.pas" + 55) + $F
(00582AE3){Main.exe     } [00983AE3] JclHookExcept.TNotifierItem.DoNotify + $43
(00582CCB){Main.exe     } [00983CCB] JclHookExcept.DoExceptNotify + $CF
(00582DAD){Main.exe     } [00983DAD] JclHookExcept.HookedExceptObjProc + $1D
(0000606F){Main.exe     } [0040706F] System.@HandleAnyException + $33
(00598DE3){Main.exe     } [00999DE3] Main.TMainForm.FormKeyDown (Line 658, "Main.pas" + 2) + $7

这是我在发布模式下获得的(使用 JCL 调试专家将 JCL 调试信息添加到二进制文件中):

Stack trace at the moment of the exception:
(0053BA27){Main.exe     } [0093CA27] DlgTraceException.TTraceForm.LogException + $377
(00536427){Main.exe     } [00937427] JclDebug.JclCreateStackList + $17
(0053BA32){Main.exe     } [0093CA32] DlgTraceException.TTraceForm.LogException + $382
(0052D60B){Main.exe     } [0092E60B] JclHookExcept.TNotifierItem.DoNotify + $43
(0052D7F3){Main.exe     } [0092E7F3] JclHookExcept.DoExceptNotify + $CF
(0052D8D5){Main.exe     } [0092E8D5] JclHookExcept.HookedExceptObjProc + $1D
(0000606F){Main.exe     } [0040706F] System.@HandleAnyException + $33

在第二种情况下,FormKeyDown 条目丢失。有人知道为什么会这样吗?我也想知道发布模式下的整个堆栈跟踪。

【问题讨论】:

  • 我认为您的发布代码可以优化可选的生成堆栈帧 - 请参阅 docwiki.embarcadero.com/RADStudio/Seattle/en/… // 并且由于没有堆栈帧 - JCL Stuck unwinder 无法检测到
  • 跟JCL标签无关,所以去掉了。
  • @MartynA 你看过 JCL 标签的文档吗?当我说“与 JCL 标签无关”时,我的意思是“与 JCL 标签无关”。 IBM 大型机操作系统上的作业控制语言。由于 Delphi 不在 IBM 大型机上运行,​​我发现很难相信该标签对问题或未来的搜索者有用。相反。所以我删除了它。在过去的几年里,我们已经有了 3-4 个这样的标签,所以如果您认为标签可以帮助问题/搜索者,请务必制作一个新标签。
  • @Arioch'和MartynA一样
  • 对不起各位,是我的错。我添加了正确的标签。

标签: delphi jedi-code-library


【解决方案1】:

在使用编译器选项(打开和关闭它们)后,我可以找出原因。堆栈帧已被优化。当我关闭优化时,即使在发布模式下也记录了 FormKeyDown 调用。上面 cmets 中提到的 Stack Frames 生成选项不影响结果。

当然,我会在发布模式下继续优化。找到异常的原因会更难,但是 JCL 调试提供的其他信息应该(希望)足以找到异常的原因。

【讨论】:

  • 其他库,例如 madExcept,具有更好质量的堆栈跟踪代码,即使经过这样的优化也可以跟踪堆栈。
  • 您可以禁用您希望出现在堆栈跟踪中的特定过程的优化,而不是整个项目。还有其他免费和商业库提供堆栈跟踪。
  • madExcept/Eurekalog 工作得更好,但它们仅适用于 Delphi 并为商业用途付费:-( 因为我们计划很快将应用程序移植到 Lazarus,所以我们需要一些在 Delphi 和那是 JCL 调试。Lazarus AFAIK 有完全不同的方法来获取有关异常的详细信息。
猜你喜欢
  • 2021-05-02
  • 1970-01-01
  • 2021-08-16
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 2019-02-19
  • 2013-03-02
相关资源
最近更新 更多