【问题标题】:How do I debug a designtime package unloading crash involving a crash in ThreadProc in Classes.pas?如何调试涉及 Classes.pas 中 ThreadProc 崩溃的设计时包卸载崩溃?
【发布时间】:2012-01-08 23:11:03
【问题描述】:

我不确定如何追踪以下崩溃:

  1. 卸载我公司内部使用的 Designtime 包时会发生这种情况。这是我们的代码,因此是我们要修复的错误,而不是第三方组件供应商的问题。

  2. 似乎涉及到一个线程,但由于它发生在 Classes.pas 中的 Function ThreadProc 中,我猜它是一个裸系统/RTL 线程,甚至没有我应该搜索的 TThread 类包装器在我们的代码中。 (问题 A 部分:是这样吗?)

  3. 调用栈不包含我的代码,只有IDE本身,调用栈中的基函数是ntdll.RtlInitializeExceptionChain。

在某些 TThread.Execute 方法中访问冲突的调用堆栈示例表明调试器没有提供有关涉及哪个线程的详细信息:

 :7599b9bc KERNELBASE.RaiseException + 0x58
 :516b4965 ; c:\program files (x86)\embarcadero\rad studio\8.0\bin\exceptiondiag150.bpl
 :5003b058 NotifyNonDelphiException + $1C
 :77be6a8b ; ntdll.dll
 :77bb0143 ntdll.KiUserExceptionDispatcher + 0xf
 rtl.Classes.ThreadProc($CB9ED70)
rtl.System.ThreadWrapper($403E910)
:75fb339a kernel32.BaseThreadInitThunk + 0x12
:77bd9ed2 ntdll.RtlInitializeExceptionChain + 0x63
:77bd9ea5 ntdll.RtlInitializeExceptionChain + 0x36

当我尝试查看线程信息时,作为我的目标可执行文件的第二个 Delphi IDE 本身崩溃,但我能够继续在我的 delphi 调试主机实例中查看信息。

我知道调试设计时包的技术,并且我正在使用这些技术。也就是说,我有第一个 delphi (BDS.exe) 副本启动第二个副本,因为包项目已在其运行参数中设置,在主机应用程序编辑框中为 Delphi XE 的主要 bds.exe。 (C:\Program Files (x86)\Embarcadero\RAD Studio\8.0\bin\bds.exe)。因此,当我在调试模式下运行我的包时,它会将自己加载到 Delphi IDE 中。

问题 B 部分是:设置断点的最佳位置是什么,以便我可以看到非 TThread 线程以及正在创建的基于 TThread 的线程?如果没有办法设置断点,那么另一种方法来查找哪些代码正在创建线程呢?

更新:我发现在 Classes.pas 中的函数 ThreadProc 中读取 Thread.Execute 的行中设置断点会在每次 TThread 启动时触发断点。这足以从其初始化部分找到由设计时或运行时包启动的线程,但我希望存在一种更低级别的方法来执行此操作。

【问题讨论】:

  • Classes.ThreadProc() 仅与 TThread 类一起使用。 RTL 中没有直接使用ThreadProc() 的“裸线程”(如果这样做会崩溃,因为ThreadProc() 会寻找调用者的TThread 对象实例来调用)。
  • 您是否尝试过在TThread 构造函数中放置一个断点,然后按照调用堆栈查看创建TThread 对象的代码是什么?在ThreadProc() 中放置断点不会告诉你。
  • 你说得对。我正在寻找一种设置断点的方法,该断点将在激活基于非 TThread 的线程时被调用。我已经有办法为 TThread 断点获取断点。
  • 为非 TThread 线程设置断点的唯一方法是直接在 Win32 API CreateThread() 函数内设置断点。
  • Remy,这实际上就是我所做的,而且由于该技术可能对世界并不明显(我从不知道你可以做到这一点,直到有人向我展示你可以打开 windows.pas 并设置断点)我已将其添加为答案。

标签: delphi debugging design-time


【解决方案1】:

我通过以下方式调试了设计时包崩溃:

  1. 如上所述,设置 Delphi 运行自身,使用运行参数,在主机应用程序中,路径为 c:\path-to-delphi-install\bin\bds.exe

  2. 在 System.pas 的函数 ThreadProc 的行中设置断点。

  3. 打开windows.pas,在30,000-33,000行附近有这样一行:

    function CreateThread; external kernel32 name 'CreateThread';

使用 F8 在上面的行上设置断点。现在,当正在调试的代码中的任何内容调用 Win32 函数时,无论是否通过 TThread,您都会得到一个断点。

【讨论】:

  • 这是一个有趣的技术,我不知道 IDE 支持它。我之前的建议是在CreateThread() 函数的inside 中放置一个断点,您可以在调试器的Assembly 视图中执行此操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多