使用WinDbg调查.NET异常(编译和加载异常)

所有.NET异常都源于System.Exception以及以下成员变量。

  • Data
  • HelpLink
  • InnerException
  • Message
  • Source
  • StackTrace
  • TargetSite

除了这些基本信息之外,System.Exception通常会添加一些成员变量,它们在其中存储特定于该类型异常的信息。这一次我想谈谈一些特殊的例外情况,我们可以深入研究,以获得比乍看起来更多的信息。
更具体地说,我将讨论以下编译或加载异常:

  • System.Web.HttpCompileException
  • System.Web.HttpParseException
  • System.IO.FileNotFoundException

这里的假设是,您已经用adplus收集了一个内存转储,并且在运行!dumpheap -type时发现堆上存在上述异常之一。

System.Web.HttpCompileException

错误消息示例:

CS0246: The type or namespace name <namespace> could not be found (are you missing a using directive or an assembly reference?)
当你看到这个异常的时候,运行!PrintException <address of HttpCompileException object>或!dumpobj中会看到如下内容:
0:005> !PrintException 02d030cc 
Exception object: 02d030cc
Exception type: System.Web.HttpCompileException
Message: External component has thrown an exception.
InnerException: <none>
StackTrace (generated):
SP IP Function
0F6FF25C 689B1B01 System.Web.Compilation.AssemblyBuilder.Compile()
0F6FF2A4 686DB64A System.Web.Compilation.WebDirectoryBatchCompiler.CompileAssemblyBuilder(System.Web.Compilation.AssemblyBuilder)
0F6FF2D4 68675054 System.Web.Compilation.WebDirectoryBatchCompiler.CompileNonDependentBuildProviders(System.Collections.ICollection)
0F6FF334 686706A2 System.Web.Compilation.WebDirectoryBatchCompiler.Process()
0F6FF35C 6867027E System.Web.Compilation.BuildManager.BatchCompileWebDirectoryInternal(System.Web.Hosting.VirtualDirectory, Boolean) 

StackTraceString: <none>
HResult: 80004005
The current thread is unmanaged
我不知道你的情况,但这些信息并不能告诉我发生了什么。这是因为异常是由外部组件(即编译器)引发的vbc.exe, csc.exe文件等等)

将此信息与我们在浏览器中获取的相同异常信息进行比较:

Compilation Error

Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: CS0246: The type or namespace name ‘BusinessStuff‘ could not be found (are you missing a using directive or an assembly reference?)
Source Error:

 Line 9:  using System.Web.UI.WebControls.WebParts;
Line 10: using System.Web.UI.HtmlControls;
Line 11: using BusinessStuff;
Line 12: 
Line 13: public partial class Default4 : System.Web.UI.Page

如果我们在堆里有这种类型的信息,清除异常可能会是小菜一碟。那么我们如何从转储中的异常中获取这些信息呢?
如果我们看一下msdn中HttpCompileException的定义,我们会发现除了标准的异常成员变量外,HttpCompileException还有两个额外的成员变量,称为Results和SourceCode。结果将填充实际的编译错误,SourceCode包含未能编译的文件的源代码。

0:005> !do 02d030cc
Name: System.Web.HttpCompileException
MethodTable: 68a5f4b4
EEClass: 68a5f434
Size: 100(0x64) bytes
(C:\WINDOWS\assembly\GAC_32\System.Web\2.0.0.0__b03f5f7f11d50a3a\System.Web.dll)
Fields:
MT Field Offset Type VT Attr Value Name
...
790fed1c 4000f97 48 System.Int32         0 instance 0        _httpCode
68a5c4d8 4000f98 44 ...eb.ErrorFormatter 0 instance 02d164c8 _errorFormatter
790fed1c 4000f99 4c System.Int32         0 instance 0        _webEventCode
7a754b50 4000f9b 50 ...r.CompilerResults 0 instance 02cd8520 _results
790fa3e0 4000f9c 54 System.String        0 instance 02d0e424 _sourceCode

在_results中,我们可以找到错误号(CS0246)、消息(找不到类型或命名空间名称“BusinessStuff”(是否缺少using指令或程序集引用?),源文件(default4.aspx.c)行号(11)如下:

 0:005> !do 02cd8520 
Name: System.CodeDom.Compiler.CompilerResults
MethodTable: 7a754b50
EEClass: 7a754ae0
Size: 36(0x24) bytes
(C:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\System.dll)
Fields:
MT Field Offset Type VT Attr Value Name
7a754bd4 4000f55 4 ...erErrorCollection 0 instance 02cd8544 errors
7a74847c 4000f56 8 ....StringCollection 0 instance 02cd8568 output
...

0:005> !do 02cd8544 
Name: System.CodeDom.Compiler.CompilerErrorCollection
MethodTable: 7a754bd4
EEClass: 7a7b07c4
Size: 12(0xc) bytes
(C:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\System.dll)
Fields:
MT Field Offset Type VT Attr Value Name
791036b0 40008f1 4 ...ections.ArrayList 0 instance 02cd8550 list

0:005> !do 02cd8550 
Name: System.Collections.ArrayList
MethodTable: 791036b0
EEClass: 79103604
Size: 24(0x18) bytes
(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
Fields:
MT Field Offset Type VT Attr Value Name
79124228 40008c0 4 System.Object[] 0 instance 02d02b68 _items
790fed1c 40008c1 c System.Int32 0 instance 1 _size
...

0:005> dc 02d02b68 
02d02b68 79124228 00000004 790f9c18 02d0281c (B.y.......y.(..
02d02b78 00000000 00000000 00000000 00000000 ................
...

0:005> !do 02d0281c 
Name: System.CodeDom.Compiler.CompilerError
MethodTable: 7a7650e4
EEClass: 7a7b79f0
Size: 32(0x20) bytes
(C:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\System.dll)
Fields:
MT Field Offset Type VT Attr Value Name
790fed1c 4000f38 10 System.Int32 0 instance 11 line
790fed1c 4000f39 14 System.Int32 0 instance 7 column
790fa3e0 4000f3a 4 System.String 0 instance 02d02a40 errorNumber
79104f64 4000f3b 18 System.Boolean 0 instance 0 warning
790fa3e0 4000f3c 8 System.String 0 instance 02d02a60 errorText
790fa3e0 4000f3d c System.String 0 instance 02d02980 fileName

0:005> !do 02d02a40 
String: CS0246

0:005> !do 02d02a60 
String: The type or namespace name BusinessStuff could not be found (are you missing a using directive or an assembly reference?) 

0:005> !do 02d02980 
String: c:\Inetpub\wwwroot\DebuggerSamples\Default4.aspx.cs

这和源代码一起会给我们提供我们通常在浏览器中看到的所有信息。

System.Web.HttpParseException

错误消息示例:
Parser Error: Could not load type ‘<namespace>.<type>‘.
这种类型的异常通常发生在部署web应用程序时,或者页面的代码未编译,或者您设置了对程序集的引用,但该程序集在开发人员计算机和客户端上的版本不同,因此您尝试访问的类型未在服务器上的版本中定义。
或者,包含类型定义的文件可能被外部进程(如病毒扫描程序、索引服务或备份软件)锁定。解决这些问题的最佳方法是查看类型和将在其中定义它的dll,并验证服务器上是否存在该dll。如果是的话,你可以从http://www.sysinternals.com至看看为什么它不能加载dll。
运行!dumpobj(!do)您将看到如下:
0:000> !do 0x184aee84 
Name: System.Web.HttpParseException
...
0x79b96824 0x4000020 0x10 CLASS instance 0x184aeed4 _message
0x79b96824 0x4000021 0x14 CLASS instance 0x184aed34 _innerException
0x79b96824 0x4000022 0x18 CLASS instance 0x00000000 _helpURL
0x79b96824 0x4000023 0x1c CLASS instance 0x184aef88 _stackTrace
0x79b96824 0x4000024 0x20 CLASS instance 0x00000000 _stackTraceString
0x79b96824 0x4000025 0x24 CLASS instance 0x00000000 _remoteStackTraceString
0x79b96824 0x4000026 0x2c System.Int32   instance 0 _remoteStackIndex
0x79b96824 0x4000027 0x30 System.Int32   instance -2147467259 _HResult
0x79b96824 0x4000028 0x28 CLASS instance 0x00000000 _source
0x79b96824 0x4000029 0x34 System.Int32   instance 0 _xptrs
0x79b96824 0x400002a 0x38 System.Int32   instance -532459699 _xcode
0x020784fc 0x4000604 0x40 System.Int32   instance 0 _httpCode
0x020784fc 0x4000605 0x3c CLASS instance 0x184aef6c _errorFormatter
0x04392114 0x4000608 0x44 CLASS instance 0x1053b41c _fileName
0x04392114 0x4000609 0x48 System.Int32   instance 1 _line
-----------------
Exception 0x184aee84 in MT 0x04392114: System.Web.HttpParseException
_message: Parser Error: Could not load type DebuggerSamples.MyPage
...

从这里我们可以查看文件名,看看我们在哪个文件中失败了:

0:000> !do 0x1053b41c 
String: C:\InetPub\wwwroot\DebuggerSamples\MyPage.aspx 

也可以在错误格式化程序中获取源代码

 0:000> !do 0x184aef6c 
Name: System.Web.ParseErrorFormatter
...
MT Field Offset Type Attr Value Name
0x052f2fec 0x4000460 0x4 CLASS instance  0x1053b41c _fileName
0x052f2fec 0x4000461 0x8 CLASS instance  0x184ae51c _sourceCode
0x052f2fec 0x4000462 0xc System.Int32    instance 1 _line
0x052f3274 0x4000467 0x10 CLASS instance 0x184aed7c _message
0x052f3274 0x4000468 0x14 CLASS instance 0x184aee84 _excep


0:000> !do 0x184ae51c 
String: <%@ Page Language="vb" AutoEventWireup="false" Codebehind="MyPage.aspx.vb" Inherits="DebuggerSamples.MyPage"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<title>MyPage</title>
<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<asp:Button id="MyButton" runat=server />
</form>
</body>
</HTML>

最后,把它们放在一起,我们可以从ErrorFormatter中看到我们使用Parser错误:Could not load type ‘DebuggerSamples.MyPage‘ on line 1 of C:\InetPub\wwwroot\DebuggerSamples\MyPage.aspx

and line 1 was <%@ Page Language="vb" AutoEventWireup="false" Codebehind="MyPage.aspx.vb" Inherits="DebuggerSamples.MyPage"%>

System.IO.FileNotFoundException

错误消息示例:File or assembly name <assembly name>, or one of its dependencies, was not found

如果进程中加载的某个dll引用了系统上不存在的dll或dll版本,则通常会看到此异常。例如,如果您正在进程中加载使用中函数的控件,则它不一定具有任何递减效果Microsoft.VisualStudio.dll或者stdole.dll用于设计时目的,但不用于运行时目的。
这是一个示例,看看!dumpobj的输出:

0:000> !do 0x1031b1fc 
Name: System.IO.FileNotFoundException
MethodTable 0x79bfbdcc
EEClass 0x79bfbe5c
Size 72(0x48) bytes
GC Generation: 2
mdToken: 0x02000345 (c:\windows\microsoft.net\framework\v1.1.4322\mscorlib.dll)
FieldDesc*: 0x79bfbec0
MT Field Offset Type Attr Value Name
0x79b96824 0x400001d 0x4 CLASS instance 0x00000000 _className
0x79b96824 0x400001e 0x8 CLASS instance 0x00000000 _exceptionMethod
0x79b96824 0x400001f 0xc CLASS instance 0x00000000 _exceptionMethodString
0x79b96824 0x4000020 0x10 CLASS instance 0x1031b244 _message
0x79b96824 0x4000021 0x14 CLASS instance 0x00000000 _innerException
0x79b96824 0x4000022 0x18 CLASS instance 0x00000000 _helpURL
0x79b96824 0x4000023 0x1c CLASS instance 0x00000000 _stackTrace
0x79b96824 0x4000024 0x20 CLASS instance 0x00000000 _stackTraceString
0x79b96824 0x4000025 0x24 CLASS instance 0x00000000 _remoteStackTraceString
0x79b96824 0x4000026 0x2c System.Int32 instance 0 _remoteStackIndex
0x79b96824 0x4000027 0x30 System.Int32 instance -2147024894 _HResult
0x79b96824 0x4000028 0x28 CLASS instance 0x00000000 _source
0x79b96824 0x4000029 0x34 System.Int32 instance 0 _xptrs
0x79b96824 0x400002a 0x38 System.Int32 instance -532459699 _xcode
0x79bfbdcc 0x4000f23 0x3c CLASS instance 0x14358078 _fileName
0x79bfbdcc 0x4000f24 0x40 CLASS instance 0x1031a570 _fusionLog
-----------------
Exception 0x1031b1fc in MT 0x79bfbdcc: System.IO.FileNotFoundException
_message: File or assembly name stdole, or one of its dependencies, was not found.

这个异常的有趣部分是_fusionLog,它告诉我们它在哪里查找dll,以及它正在寻找的特定版本以及找不到它的原因。

0:000> !do 0x1031a570 
String: === Pre-bind state information ===
LOG: DisplayName = stdole, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
(Fully-specified)
LOG: Appbase = file:///c:/inetpub/wwwroot/DebuggerSamples
LOG: Initial PrivatePath = bin
Calling assembly : (Unknown).
=== 
LOG: Publisher policy file is not found.
LOG: No redirect found in host configuration file (C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\aspnet.config).
LOG: Using machine configuration file from C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\config\machine.config.
LOG: Post-policy reference: stdole, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
LOG: Attempting download of new URL file:///C:/WINDOWS/Microsoft.NET/Framework/v1.1.4322/Temporary ASP.NET Files/DebuggerSamples/e2b59b51/5bf1057f/stdole.DLL.
LOG: Attempting download of new URL file:///C:/WINDOWS/Microsoft.NET/Framework/v1.1.4322/Temporary ASP.NET Files/DebuggerSamples/e2b59b51/5bf1057f/stdole/stdole.DLL.
LOG: Attempting download of new URL file:///c:/inetpub/wwwroot/DebuggerSamples/bin/stdole.DLL.
LOG: Attempting download of new URL file:///c:/inetpub/wwwroot/DebuggerSamples/bin/stdole/stdole.DLL.
LOG: Attempting download of new URL file:///C:/WINDOWS/Microsoft.NET/Framework/v1.1.4322/Temporary ASP.NET Files/DebuggerSamples/e2b59b51/5bf1057f/stdole.EXE.
LOG: Attempting download of new URL file:///C:/WINDOWS/Microsoft.NET/Framework/v1.1.4322/Temporary ASP.NET Files/DebuggerSamples/e2b59b51/5bf1057f/stdole/stdole.EXE.
LOG: Attempting download of new URL file:///c:/inetpub/wwwroot/DebuggerSamples/bin/stdole.EXE.
LOG: Attempting download of new URL file:///c:/inetpub/wwwroot/DebuggerSamples/bin/stdole/stdole.EXE.

找不到发布者策略文件通常意味着在任何应用程序“路径”中都找不到请求的dll。

 

使用WinDbg调查.NET异常(编译和加载异常)

上一篇:C#和sql语句中切割函数SUBSTRING的用法和区别


下一篇:Mysql中的降序索引底层实现