你怎么能找到谁在delphi程序中创建所有线程?

War*_* P 7 delphi debugging multithreading

如果你有一套干净的Delphi代码,并且所有线程都是使用TThread创建的,你可以在构造函数方法(TThread.Create)中设置一个断点,并找出谁创建了你的线程.您甚至可以尝试使用Delphi TThread对象中内置的功能命名所有线程,该功能允许您为每个线程设置调试名称.

但是,如何确定持久的,难以发现的额外线程,这些线程仍然是匿名的(无调试名称),并且在模块初始化时出现,因为应用程序启动时.我可以单步执行模块初始化,但是我无法确定可能创建线程的所有源模块(例如,已完成的900多个模块初始化部分),我还没有想出办法添加一个调试消息(使用断点属性和消息),它将在初始化时转储每个单元名称.在System.pas中设置断点的创造性使用,使用logging-messages允许我在调试简单的简单应用程序时做一些事情,但是我的应用程序越复杂越多,我觉得线程越盲,两者都是在中间创建的应用程序运行,以及在模块初始化时创建的那些(即在您进入项目dpr中代码的第一行之前).

我想知道您可能找到哪些高级技术来识别和确定谁创建了特定线程.如果我们使用像GDB这样的调试器而不是像delphi IDE中内置的delphi调试器内核(Turbo Debugger?)这样的调试器,我认为我们可以在windows api函数上设置一个断点,比如BeginThread本身.但我不认为我能在Delphi中做到这一点.

更新:我不知道你可以在windows.pas的实现部分为kernel32.dll之类的外部windows dll设置一个断点.

更新2:似乎David H的回答是一般用途的最佳选择.我也正在研究一个我正在编写的小帮助代码库,它维护一个之前已经看过的线程id的字典,并根据它们的创建时间将一些调试名称分配给其他未命名的线程(函数是什么)我们在注意到新线程存在之前就已经调用了.我认为这将帮助我缩小40多个编号的线程,以便它们都被命名,即使其中一些是在外部C/C++ dll或COM进程中创建的.

Dav*_*nan 9

我可能会使用像Process ExplorermadExcept这样的工具,但是有很多工具可以提供帮助.

我不相信Delphi使用Turbo Debugger.更重要的是Delphi完全能够在像CreateThread这样的kernel32入口点上设置断点.

我将在启用Debug DCU的情况下运行,并在Windows.pas中设置CreateThread实现的断点.一旦中断,切换到CPU窗口并进入例程.你会看到一条JMP DWORD PTR [address]指令.跳过这个,嘿presto,你现在正在kernel32中调试.您可以在此处设置断点.

现在,如果您重置应用程序并再次开始调试,那么您将打破对来自您的进程的kernel32.CreateThread的所有调用.检查调用堆栈将告诉您如何到达那里.它看起来像这样:

在此输入图像描述

最后,我不确定为什么你的应用程序创建线程感到困扰.大多数体面的应用程序创建了大量的线程 - 这样做是完全正常的.你遇到了什么问题?


gab*_*abr 6

...我认为我们可以在Windows api函数上设置一个断点,比如BeginThread本身.但我不认为我能在Delphi中做到这一点.

你当然可以.

  • 启用项目,选项,Delphi编译器,编译,调试,使用调试.dcus.(这是在Delphi XE中找到它的方法,不同Delphi版本的确切位置可能不同).

  • 重新编译.

  • 打开系统单元并在BeginThread函数中的Result:= CreateThread ...上放置断点.

  • 运行程序并等待直到触发断点.

  • 打开CPU窗口(查看,调试Windows,CPU Windows,整个CPU).

CPU窗口将显示如下内容:

System.pas.16559: Result := CreateThread(SecurityAttributes, StackSize, @ThreadWrapper, P,
00406A97 8B4508           mov eax,[ebp+$08]
00406A9A 50               push eax
00406A9B 8B450C           mov eax,[ebp+$0c]
00406A9E 50               push eax
00406A9F 53               push ebx
00406AA0 B81C6A4000       mov eax,$00406a1c
00406AA5 50               push eax
00406AA6 8B45F8           mov eax,[ebp-$08]
00406AA9 50               push eax
00406AAA 8B45FC           mov eax,[ebp-$04]
00406AAD 50               push eax
00406AAE E855BBFFFF       call CreateThread
00406AB3 8BF0             mov esi,eax
Run Code Online (Sandbox Code Playgroud)
  • 单击"调用CreateThread"行中的CPU窗口.

  • 按F4.

  • 按F7.

您将被定位在调度表中:

CreateThread:
00402608 FF2594AA4F00     jmp dword ptr [$004faa94]
0040260E 8BC0             mov eax,eax
Run Code Online (Sandbox Code Playgroud)
  • 按F5键将断点放在此处.

  • 重新运行程序(Ctrl-F2,F9).

每次创建线程时都会触发断点.断点似乎发生在WindowsAPIs.INC中

function CreateThread(SecurityAttributes: Pointer; StackSize: LongWord;
                     ThreadFunc: TThreadFunc; Parameter: Pointer;
                     CreationFlags: LongWord; var ThreadId: LongWord): Integer; stdcall;
  external kernel name 'CreateThread';
Run Code Online (Sandbox Code Playgroud)

(至少在Delphi XE中).

可能仍然会错过一些线程创建调用.我不知道这个方法是否会捕获Direct X内部创建的线程,例如.