2015-07-22 68 views
8

Windbg should understandMS exception protocol用于将线程名称传递给调试器。Can Windbg可以显示线程名称吗?

我不能得到这个工作。看网上有很多例子显示“〜”线程列表没有线程名称,这就是我看到的。我正在调试一个.NET x86进程,并且我尝试了Windbg的WDK 8.1 x86和x64版本。

有谁知道此功能是否仍然可用?我错过了什么?

+0

我使用WinDbg的自2010年以来,我从来没有见过这样的 –

+0

的职位是从2005年线程的名字,所以你可能会使用WinDbg 6.4.0007.0尝试(找到它在[ Windows 2003 SDK](http://download.cnet.com/Windows-Server-2003-R2-Platform-SDK-ISO-Download/3000-10248_4-10731094.html)) –

回答

7

对于.NET线程,为“正常” Thread秒(手动创建的线程,因为我不知道的方式来命名线程池线程)以下工作:

一个Thread是一类,因此可以在.NET中托管堆:

0:000>.loadby sos clr 
0:000> !dumpheap -stat -type Thread 
     MT Count TotalSize Class Name 
... 
725e4960  11   572 System.Threading.Thread 

注意,有其他输出为好,因为!dumpheap查找类名的部分。方法表(MT),然而,标识一类独特的,所以这就是我们从现在开始使用:

0:000> !dumpheap -short -mt 725e4960 
023123d0 
02312464 
02313c80 
... 

这些Thread对象的地址。由于它是干净的输出,我们可以在一个循环中使用它:

0:000> .foreach (address {!dumpheap -short -mt 725e4960}) {.echo ${address} } 
023123d0 
02312464 
02313c80  
... 

在循环中,我们可以使用的地址,以获得有关线程的详细信息。首先,让我们看看一个线程的模样内部:

0:000> !do 023123d0 
Name:  System.Threading.Thread 
... 
Fields: 
     MT Field Offset     Type VT  Attr Value Name 
... 
725e3e18 400076e  c  System.String 0 instance 02313c0c m_Name 
... 

在偏移+0xC,还有的m_Name成员(取决于位数!)。这是一个字符串。让我们来看看一个字符串的样子:

0:000> !do poi(023123d0+c) 
Name:  System.String 
... 
Fields: 
     MT Field Offset     Type VT  Attr Value Name 
... 
725e4810 40000ac  8   System.Char 1 instance  4d m_firstChar 

因此,该字符串的第一个字符是在偏移+0x08。在.NET中的字符串都是Unicode,所以我们可以用du查看:

0:000> du poi(023123d0+c)+8 
02313c14 "My named thread 0" 

结合所有这些知识转化为一个命令:

.foreach (address {!dumpheap -short -mt 725e4960}) 
{ 
    du poi(${address}+c)+8 
} 

(格式化的可读性,把它所有在同一行)

如果你尝试,你会发现,它可以输出像

00000008 "????????????????????????????????" 

这发生在m_Namenull。如果你关心的是,你可以添加一个检查空:

.foreach (address {!dumpheap -short -mt 725e4960}) 
{ 
    .if (poi(${address}+c) != 0) { 
     du poi(${address}+c)+8 
    } 
} 

(格式化的可读性,把它所有在同一行)

其他方面的改进:

  • 做同样的线程ID
  • 美化输出(使用.printf代替dddu

最终结果:

.foreach (address {!dumpheap -short -mt 725e4960}) 
{ 
    .if (poi(${address}+c) != 0) 
    { 
     .printf "%d ",poi(${address}+28); 
     .printf "%mu\r\n", poi(${address}+c)+8 
    } 
} 
+0

线程池线程与常规线程没有区别,但是为它们命名通常没有意义,因为它们被重用。 –

+0

看来.NET并没有为线程名称使用第一次机会异常协议,尽管我没有时间去验证它。感谢您的教程。我已将您的脚本添加到我很少使用的WinDbg备忘单中! –

+0

我希望我可以多次提出这个答案。 – mark

0

有谁知道此功能是否仍然可用?

是的,此功能仍然可用。至少对于本机应用程序。

对于.NET应用程序,来自'How to: Set a Thread Name in Managed Code'的方法可能比抛出异常更受欢迎。

+2

你在说什么功能?命名线程或在WinDbg中显示命名线程?请详细说明如何在WinDbg中显示线程名称。 –