8

我有一个我制作的 Windows 服务的转储。例外是我的代码无法移动文件(出于某种原因)。现在,在我的代码中有很多地方可以在文件系统中移动文件。因此,使用 Windbg,我试图查看发生异常的代码。

这是我的 !clrstack 转储..

0:016> !clrstack -p
OS Thread Id: 0xdf8 (16)
Child-SP         RetAddr          Call Site
0000000019edea70 0000064278a15e4f System.IO.__Error.WinIOError(Int32, System.String)
PARAMETERS:
    errorCode = <no data>
    maybeFullPath = <no data>

0000000019edead0 0000064280181ce5 System.IO.File.Move(System.String, System.String)
PARAMETERS:
    sourceFileName = <no data>
    destFileName = <no data>

0000000019edeb50 0000064280196532 MyClass.Foo.DoSomeStuffInHere(System.String)
PARAMETERS:
    this = 0x0000000000c30aa8
    filePathAndName = 0x0000000000d1aad0

现在,这有很大帮助...

0:016> !do 0x0000000000d1aad0
Name: System.String
MethodTable: 00000642784365e8
EEClass: 000006427803e4f0
Size: 88(0x58) bytes
(C:\WINDOWS\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: C:\BlahBlahFolder\FooFolder\4469.jpg
Fields:
-snipped-

所以我找出了无法移动的文件。科尔。但我只想查看调用 File.Move(..) 的 MyClass.Foo.DoSomeStuffInHere(System.String) 方法中的代码。该方法有很多 File.Move .. 所以我可以放 try / catches / debug / trace 信息.. 但我希望通过使用 Windbg 来帮助找到这个问题来提高效率。

有什么想法吗?

4

2 回答 2

3

除非应用程序以调试模式部署,否则您无法获得确切的代码行。如果是这样的话,我相信它会在 !clrstack 调用中显示它们。

于 2008-10-31T01:28:59.347 回答
3

这是一个难题,可能需要跳出仅托管调试的舒适区。

您要做的是将函数MyClass.Foo.DoSomeStuffInHere的 IL 映射到该函数的反汇编。我下面的示例是 x86,但是 x64 可以遵循相同的步骤。

这在以下链接的深处被引用。 调试意外的进程终止

白皮书中的示例文本:在托管堆栈中,Debugging.Unexpected.btnSTA_Click ... 查看 Debugging.Unexpected.btnSTA_Click 事件中的代码。

private void btnSTA_Click(object sender, System.EventArgs e)
{
   DebuggingCOMLib.STAClass staobj =  new DebuggingCOMLib.STAClass();
   staobj.RaiseError(1,5);
   Label1.Text += "STA Call Completed sucessfully";
}

如果源代码不可用,您可以通过将调用堆栈帧的指令指针提供给!u 命令来检查程序集。可以从 !clrstack: 输出中检索指令指针。

0096f970  03a00e06 [DEFAULT] [hasThis] Void
Debugging.Unexpected.btnSTA_Click(Object,Class System.EventArgs)

要反汇编此函数,请键入!u 03a00e06

    0:010> !u 03a00e06 
    Normal JIT generated code
    [DEFAULT] [hasThis] Void Debugging.Unexpected.btnSTA_Click(Object,Class 
    System.EventArgs)
    Begin 03a00de0, size 54
   <snip>
    03a00e18 8b15a89c1702     mov     edx,[02179ca8] ("STA Call Completed 
    sucessfully")
    03a00e1e e83d3590ff       call    03304360 (System.String.Concat)
    <snip>
    03a00e2f 5e               pop     esi
    03a00e30 5f               pop     edi
    03a00e31 c20400           ret     0x4

好的,现在呢?
扫描您自己的 !u 输出以查找类似的行

call    03304360 (System.IO.File.Move)

此外,您可以运行 !ip2md 03a00e06来获取 MethodDesc,然后运行​​!dumpil来检查 IL 代码,如果这样更容易的话。

您可以在!u 输出中计算对System.IO.File.Move的调用次数,然后在 IL 中倒数相同的数字。然后您可以使用 .NET Reflector 反汇编该方法并将 C# 映射到 IL 并比较结果。

很多步骤,但它会让你得到相同的结果:-)

谢谢,亚伦

于 2009-02-21T23:14:41.117 回答