Delphi 如何调试designtime包卸载崩溃,该崩溃涉及Classes.pas中的ThreadProc崩溃?

Delphi 如何调试designtime包卸载崩溃,该崩溃涉及Classes.pas中的ThreadProc崩溃?,delphi,debugging,design-time,Delphi,Debugging,Design Time,我不确定如何追踪以下车祸: 它发生在卸载我公司内部使用的Designtime软件包时。这是我们的代码,因此需要修复的是我们的bug,而不是第三方组件供应商的问题 它似乎涉及到一个线程,但由于它发生在Classes.pas中的函数ThreadProc中,我猜它是一个裸系统/RTL线程,甚至没有我应该在代码中搜索的TThread类包装器。(问题A部分:是这样吗?) 调用堆栈不包含我的代码,只包含IDE本身,调用堆栈中的基函数是ntdll.RtlInitializeExceptionChain 某些T

我不确定如何追踪以下车祸:

  • 它发生在卸载我公司内部使用的Designtime软件包时。这是我们的代码,因此需要修复的是我们的bug,而不是第三方组件供应商的问题

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

  • 调用堆栈不包含我的代码,只包含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:\ProgramFiles(x86)\Embarcadero\RAD Studio\8.0\bin\bds.exe
    )。因此,当我在调试模式下运行包时,它会将自己加载到DelphiIDE中

    问题B部分是:设置断点的最佳位置是什么,这样我就可以看到正在创建的非TThread线程以及基于TThread的线程?如果无法设置断点,那么使用另一种方法来查找正在创建线程的代码如何


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

    我以以下方式调试了designtime包崩溃:

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

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

  • 打开windows.pas,在第30000-33000行附近有一行如下所示:

    函数CreateThread;外部内核32名称“CreateThread”

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


    Classes.ThreadProc()
    仅与
    TThread
    类一起使用。RTL中没有直接使用
    ThreadProc()
    的“裸线程”(如果这样做,它将崩溃,因为
    ThreadProc()
    查找调用方的
    TThread
    对象实例以调用)。您是否尝试过在
    TThread
    构造函数中放置断点,然后跟随调用堆栈查看要从哪个代码开始创建
    TThread
    对象?在
    ThreadProc()
    中放置断点不会告诉您这一点。您说得对,雷米。我正在寻找一种方法来设置一个断点,当一个非基于TThread的线程被激活时,该断点将被调用。我已经有了一种为TThread断点获取断点的方法。为非TThread线程设置断点的唯一方法是直接在Win32 API
    CreateThread()
    函数中设置断点。Remy,事实上我就是这么做的,因为这项技术对世界来说可能并不明显(直到有人告诉我你可以打开windows.pas并设置断点,我才知道你可以这么做)我添加了它作为答案。这是一种有趣的技术,我不知道IDE支持它。我之前的建议是在
    CreateThread()中设置断点
    函数,您可以在调试器的程序集视图中执行此操作。