在Visual Studio调试器中中断线程创建

时间:2010-09-29 10:46:56

标签: visual-studio multithreading debugging

我可以将Visual Studio调试器设置为在创建线程时中断吗?

(请注意,这与在其他问题中要求的上下文切换不同:Can I set a breakpoint in Visual Studio (c++) to break on a thread context switch?

6 个答案:

答案 0 :(得分:8)

我找到了办法。谷歌搜索时,我看到了相反的问题: Is it possible to break on thread exit with specific error code?

我在函数RtlExitUserThread放了一个断点,之后我意识到所有线程都是用函数RtlUserThreadStart创建的,所以把另一个断点放到那个函数上就是全部:)

答案 1 :(得分:3)

如果您知道线程是由托管的Thread类创建的,那么一个简单的解决方案是在其条目上放置一个断点(通过转到Breakpoints窗口,单击New-> Break at function并标记Thread。开始)。

否则,正如汉斯所说,你将不得不使用更复杂的解决方案,如mdbg,或使用CLR探查器的开源实现(如SAE)并在其中放入“asm int 3”指令ICorProfilerCallback :: ThreadCreated方法。

另外,如果你有VS2010 Ultimate,你可以在Intellitrace事件中查找Thread Created事件,并可能从那里获得你需要的信息(虽然这不会在创建线程时中断,而是给你一些回想起来,有关堆栈跟踪/变量值在创建时的信息。

答案 2 :(得分:2)

是的,调试器会收到通知。不,UI不允许您告诉它打破该通知。如果这是托管代码,那么您可以使用MDbg示例并对其进行修改。

答案 3 :(得分:2)

正如@George所解释的,你可以打破两个功能。如果你想找出创建新线程的内容,你应该在创建WINAPI函数调用的线程上中断,例如CreateThread_beginthread(ex)。如果你想进入新创建的线程的开始(在该线程本身的调用堆栈上),你应该进入RtlUserThreadStart

但是,有两个先决条件可以闯入其中任何一个:

<强> 1。需要启用从Microsoft服务器下载符号

要使断点起作用,调试器需要知道本机dll的一些基本符号信息。确保已启用MS服务器的符号加载(工具 - &gt;选项 - &gt;调试 - &gt;符号)

<强> 2。您需要目标函数的实际stdcall签名

出于某种原因,即使启用了导出加载,VS也无法找到我需要为我打破的功能。所以我去检查实际的签名是什么。这可以通过使用dumpbin cmd line tool of VS或对代码进行简短测试来完成:

void* ptr = CreateThread;

在调试器中运行此代码会显示CreateThread的地址和签名,例如_CreateThreadStub@24对我来说(Win7 32位应用程序)。 RtlUserThreadStart对我来说是___RtlUserThreadStart@8

第3。设置断点

现在它就像选择Debug一样简单 - &gt;新断点 - &gt;打破功能。对于函数名称,您可以放置​​_CreateThreadStub@24___RtlUserThreadStart@8,剩下的就是。

然后在创建新线程时触发。

<强>观察

_CreateThreadStub@24似乎涵盖了CreateThread,_beginthread和_beginthreadex函数。

答案 4 :(得分:1)

当你想要打破线程创建时,至少有2个潜在的事情可能意味着:

  1. 在创建新线程之前打破创建线程
  2. 在调用用户提供的函数之前,在新线程内部中断。
  3. 对于第一个选项,您需要在CreateThread,_beginthread或_beginthreadex中断。

    对于第二个选项,您需要在RtlUserThreadStart或BaseThreadInitThunk中断,以便在调用用户代码之前在执行的早期捕获新线程。

    不幸的是,如果使用我上面列出的函数名创建一个断点,Visual Studio将不会破坏这些函数,至少在默认情况下不是这样。问题是,对于本机调试,默认情况下它不会加载DLL导出,如果没有,调试器不知道在哪里可以找到我上面提供的名称。

    在开始调试之前,在Visual Studio中转到工具,选项,调试,然后展开左窗格中的调试选项树。然后单击“native”并选中“Load DLL Exports”。然后,您可以再次开始调试可执行文件。

    之后,您应该能够通过输入名称在我提到的任何函数上创建断点。您可能需要或不需要通过使用以下名称创建断点来指定函数所在的DLL:

    {,, KERNEL32.DLL} CreateThread的

    {,, NTDLL.DLL} RtlUserThreadStart

    我从这里开始获得这些信息:

    https://blogs.msdn.microsoft.com/reiley/2011/07/26/debugging-tips-for-multi-threaded-application/

    自己做一些实验。我知道这是对旧问题的回应,但我希望这可以节省其他人在尝试调试线程启动时立即发生的崩溃时遇到的一些痛苦。

答案 5 :(得分:0)

您可以在第一次拨打CreateThread时设置断点(也许您为此目的插入了一个假电话)。 点击后,从源代码视图更改为Disassemly View并进入呼叫。浏览ImportLib-Code并设置断点。不完美,但它有效。