.Net 調式案例—實驗2 崩潰(Crash)複習回顧

.Net 調式案例實驗2 崩潰(Crash)複習回顧 數據庫

如今發佈第二個實驗,後面會發佈一個有關內存的實驗。 windows

問題在現 瀏覽器

1) 瀏覽 http://localhost/BuggyBits/Reviews.aspx 這個頁面。 app

2) 點擊刷新按鈕,這會致使w3wp.exe 進程,iis5 上面是aspnet_wp.exe 框架

注意:若是你安裝了Visual Studio,一個「Just-In-Time」的調試對話框會彈出來(點擊「否」),然而,這個消息框會始終在那裏並等待用戶輸入而後結束這個應用程序,你能夠禁止JIT調試,方法:把註冊表中的下面兩個鍵值刪除掉: asp.net

·HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ ide

Windows NT\CurrentVersion\AeDebug\Debugger 函數

·HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\ 工具

DbgManagedDebugger this

若是是64位的系統,還應該把下面兩個刪除:

·HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\

Windows NT\CurrentVersion\AeDebug\Debugger

·HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\

DbgManagedDebugger

檢查事件查看器

1) 打開應用程序和系統的事件查看器,下面的信息會因操做系統合iis版本的不一樣而有所差異,但大概意思都是同樣的

Event Type: Warning

Event Source: W3SVC

Event Category: None

Event ID: 1009

Date:2008-02-08

Time: 10:12:06

User: N/A

Computer: MYMACHINE

Description:

A process serving application pool 'DefaultAppPool' terminated unexpectedly. The process id was '4592'.

The process exit code was '0xe0434f4d'.

For more information, see Help andSupportCenterat

http://go.microsoft.com/fwlink/events.asp.

Q:你看到了什麼事件?

A:在個人機器上(Win2k3.net2.0 sp1),我獲得了上面的如上面的系統事件日誌和以下面的兩個應用程序日誌,從第一個咱們能夠看到有某種類型的nullreference 的異常。

Event Type: Error

Event Source: .NET Runtime 2.0 Error Reporting

Event Category: None

Event ID: 5000

Date:2008-02-11

Time: 11:13:18

User: N/A

Computer: MYMACHINE

Description:

EventType clr20r3, P1 w3wp.exe, P2 6.0.3790.3959,………………

第二個錯誤徹底的給咱們講清楚了是一個空引用的異常,它發生在Review類的

finalizer/destructor中,咱們所獲得的好處是,咱們不須要去再w2k3 中去調試,基於IIS、操做系統和.net框架的幫助,咱們就獲得了第二個錯誤。

Event Type: Error

Event Source: ASP.NET 2.0.50727.0

Event Category: None

Event ID: 1334

Date:2008-02-11

Time: 11:13:15

User: N/A

Computer: PRATHER

Description:

An unhandled exception occurred and the process was terminated.

Application ID: /LM/W3SVC/1/Root/BuggyBits

Process ID: 4944

Exception: System.NullReferenceException

Message: Object reference not set to an instance of an object.

StackTrace: at Review.Finalize()

Q:這個0xe0434f4d 退出碼什麼意思?

A:這個錯誤代碼是表明 dotnet異常的本地(原生)錯誤代碼,任何dotnet的錯誤異常都會被轉換成0xe0434f4d,不管dotnet 的錯誤是SQLException, NullReferenceException 仍是 FileNotFoundException

Q:你能說出是什麼緣由致使了崩潰的發生麼?

A:在上面說起的例子中,第二個異常的事件報告說明了原應。進程的崩潰是由於沒有被捕獲的在finalizer 線程中的一個空引用的異常。

獲得一個dump文件

1) 轉到瀏覽器的http://localhost/BuggyBits/Reviews.aspx 這個頁面,但不要點擊刷新。

2) 打開一個命令行窗口,切換到調試器目錄,輸入:

adplus -crash -pn w3wp.exe

敲回車。

Q:一個新的windows窗口會出如今工具欄上,它是什麼?

A:這是一個調試器,若是你最大化它,你會看見命令窗口,cdb正在運行,cdb是命令行方式下的WinDbg

Q:調試器在等待什麼?提示:查看 Adplus 有關crash的幫助。

A:下面是一個表格,顯示了adplus監視器默認的 事件(events/ 異常(exceptions),和它會作什麼,當發生這些事件時。

一些縮寫字母的含義:L=Log entry in debuglog, T=Record Time, S=Log stack, M=Mini dump, F=Full dump, E=log in the eventlog。你能夠本身編寫一個adplus 的配置文件,來改變這些事件被處理的方式。

Code

Exception/Event

Explanation/Note

1st Chance

2nd Chance

av

Access Violation

An attempt to access to uninitialized memory.
This is also thrown for .net NullReferenceExceptions

LTSM

LTSFE

ch

Invalid Handle

An attempt to access data using an invalid handle. Eg. window, file or other native handle.

LTSM

LTSFE

ii

Illegal Instruction

An attempt is made to execute an invalid instruction.

LTSM

LTSFE

dz

Integer divide

Integer divide by zero. Even in .net.

LTSM

LTSFE

c000008e

Floating divide

Floating point divide by zero.

LTSM

LTSFE

iov

Integer overflow

An attempt to store more than 32/64 bits in an integer.

LTSM

LTSFE

lsq

Invalid Lock Sequence

An attempt is made to execute an invalid lock sequence.

LTSM

LTSFE

sov

Stack overflow

The memory used for the stak (method pointers, parameters, local vars etc.) exceeds the amount allocated for the stack. Typically caused by recursion.

LTSM

LTSFE

eh

C++ EH exception

C++ EH Exception

LTS

LTSFE

*

Unknown exception

Any exception not specifically defined in this list

LTS

LTSFE

clr

.NET Exception

Any .net exception

-

LTSFE

bpe

Breakpoint

A break point is hit or the debugger window is shut down.

LTSME

-

wkd

Wake Debugger

Wake debugger.

LTSME

-

ld

Dll Load

A dll is loaded in the process

L

L

ud

Dll Unload

A dll is unloaded from the process

L

L

epr

Exit Process

The process exits.

LTSFE

-

aph

Application Hang

The Windows OS has determined that the process is no longer responding.

LTSM

LTSFE

cce

Ctrl+C Console App

Ctrl+C or Ctrl+Break is passed to a console app.

LTSM

LTSFE

dm

Data Misaligned

A unit of data is read from or written to an address that is not a multiple of the data size.

LTSM

LTSFE

gp

Guard page violation

An attempt to access data within a guard page.

LTSM

LTSFE

ip

In Page IO Error

I/O Error

LTSM

LTSFE

isc

Invalid System Call

Invalid System Call

LTSM

LTSFE

sbo

Stack Buffer overflow

Stack buffer overflow

LTSM

LTSFE

3) 再現問題,點擊那個瀏覽器的刷新按鈕。

Q:在dump目錄下什麼文件被建立了 ?提示:dump的文件夾在帶有crash模式的名字和今天的日期時間的調試器路徑下。

A :下面的文件是個人crash模式文件夾

ADPlus_report.txt

<DIR> CDBScripts

PID-4628__W3WP.EXE__Date_02-11-2008__Time_13-14-0808.log

Process_List.txt

PID-4628__W3WP.EXE__1st_chance_AccessViolation__mini_17a4_2008-02-11_13-14-19-358_1214.dmp

PID-4628__W3WP.EXE__1st_chance_Process_Shut_Down__full_17a4_2008-02-11_13-14-31-889_1214.dmp

PID-4628__W3WP.EXE__2nd_chance_NET_CLR__full_17a4_2008-02-11_13-14-20-093_1214.dmp

看看幾個重點地地方:咱們有一個1st(第一次)的違背正常訪問 mini dump(最小化dump,多是咱們的NullReferenceException)。緊跟在進程關閉(shutdowndump文件後面,還有2nd(第二次)的CLR 異常(和NullReferenceException 同樣,可是如今是2dn,由於它尚未被處理)。你能夠經過按照時間排序的順序來觀察它們。

WinDbg中打開dump文件

1) 打開帶有「2nd Chance CLR Exception」這些字樣的dump文件,注意到,這個dump文件在1st 的進程被shutdown後建立。注意:若是你有一個異常,你有再try/catch塊中處理它們的機會。它第一次被拋出來,就成爲1st 異常且不是致命的。若是你不處理它,它會變成2nd 異常,任何2nd的異常會中斷進程。

2) 設置符號文件的路徑。

crash dump文件中,活動線程是致使異常的那個線程(由於dump是由一個異常觸發)。

Q:哪個線程是活動的,當你打開dump文件後?提示:看看WinDbg的命令提示符的工具欄

A:活動的線程是#20,我能夠用它來和 !thread (輸出是Finalizer 的線程)做比較,獲得更多信息。

20 2116c001ac540 b220 Enabled02f0d28c:02f0f130 00199400 0 MTA (Finalizer)

System.NullReferenceException (02f0cb3c)

!thread 的輸出中,咱們還能夠看出該線程拋出了NullReferenceException,這個異常的地址是0x02f0cb3c

檢查調用堆棧和異常

1) 檢查本地(原生)和託管堆棧。

kb 2000

!clrstack

Q:線程是什麼類型的?

A:從kb的輸出中咱們看到事實上是finalizer線程,可是!clrstack 並無給咱們完整的更多的有關託管堆棧的信息。看起來,咱們是在異常處理代碼的內部了。

0:020> kL 2000

ChildEBP RetAddr

02a0f9d879f071ackernel32!RaiseException+0x53

02a0fa387a10733d mscorwks!RaiseTheExceptionInternalOnly+0x2a8

02a0fa507a1073b1 mscorwks!RaiseTheException+0x4e

02a0fa787a1073e2 mscorwks!RealCOMPlusThrowWorker+0x71

02a0faa47a1073f0 mscorwks!RealCOMPlusThrow+0x30

02a0fab47a14f0d4 mscorwks!RealCOMPlusThrow+0xd

02a0fbe47a025a5b mscorwks!Thread::RaiseCrossContextException+0x41f

02a0fc9879f01747 mscorwks!Thread::DoADCallBack+0x293

02a0fcb879f04a71 mscorwks!ManagedThreadBase_DispatchInner+0x47

02a0fcc479f04b01 mscorwks!ManagedThreadBase::FinalizerAppDomain+0x25

02a0fd20 79efe5b4 mscorwks!SVR::DoOneFinalization+0x141

02a0fda8 79efe70amscorwks!SVR::FinalizeAllObjects+0x56

02a0fdc0 79ef3207 mscorwks!SVR::GCHeap::FinalizerThreadWorker+0xe7

02a0fdd4 79ef31a3 mscorwks!ManagedThreadBase_DispatchInner+0x4f

02a0fe68 79ef30c3 mscorwks!ManagedThreadBase_DispatchMiddle+0xb1

02a0fea4 79fb9643 mscorwks!ManagedThreadBase_DispatchOuter+0x6d

02a0fecc 79fb960d mscorwks!ManagedThreadBase_NoADTransition+0x32

02a0fedc 79fd0c91 mscorwks!ManagedThreadBase::FinalizerBase+0xd

02a0ff1479f95a2e mscorwks!SVR::GCHeap::FinalizerThreadStart+0xbb

02a0ffb8 7d4dfe21 mscorwks!Thread::intermediateThreadProc+0x49

02a0ffec 00000000 kernel32!BaseThreadStart+0x34

0:020> !clrstack

OS Thread Id: 0x116c(20)

ESP EIP

02a0fa8c7d4e2366 [GCFrame:02a0fa8c]

02a0faf0 7d4e2366 [GCFrame:02a0faf0]

02a0fcec 7d4e2366 [GCFrame:02a0fcec]

Q:線程在幹什麼?

A:它正在嘗試調用對象的finalizer方法,正在作這個的時候,它拋出了一個異常,該異常正在被看成2nd的異常被再次拋出。

2) 檢查異常拋出。

!pe 注意:!pe/!PrintException若是沒有跟參數會打印出在棧上的當前全部異常。

Q:什麼樣的異常?

A:一個NullReferenceException 異常

0:020> !pe

Exception object:02f0cb3c

Exception type: System.NullReferenceException

Message: Object reference not set to an instance of an object.

InnerException:

StackTrace (generated):

StackTraceString:

HResult: 80004003

注意:在一個案例中,好比在這裏,異常被再次拋出,原先的棧跟蹤可能會不可見,在這種狀況下,若是你找到原先的異常你會獲得更多的信息。

3)查看棧上的對象,找到原先的異常的地址

!dso

Q:原先異常的地址是什麼?提示:看看你剛纔的!pe 的輸出的再次拋出的異常的對象的地址,把它和對象棧中的地址比較,你可能會有不少異常,一些是再次拋出的異常的地址,但在底部有一個異常,你看,那就是原先的異常(查找地址不一樣的那個)。

A:惟一的一個地址和前面列出的(0x2f0cb3c)不一樣的是0x6f1e5e4

0:020> !dso

OS Thread Id: 0x116c(20)

ESP/REG Object Name

02a0f9f402f0cb3cSystem.NullReferenceException

02a0f9f802f0cb3cSystem.NullReferenceException

02a0fa4002f0cb3cSystem.NullReferenceException

02a0fa5802f0cb3cSystem.NullReferenceException

02a0faac02f0cb3cSystem.NullReferenceException

02a0fabc02f0cb3cSystem.NullReferenceException

02a0fb5806f1e5e4 System.NullReferenceException

02a0fb5c02f0bd70 System.Byte[]

02a0fb7802f0cb3cSystem.NullReferenceException

02a0fb7c02f0bd70 System.Byte[]

02a0fb8c02f0bd70 System.Byte[]

02a0fc58 06eb281cSystem.RuntimeType

02a0fcb0 02efd4b0 Review

4)打印出原先的異常,查看輸出的信息。

!pe <original exception address>

0:020> !pe06f1e5e4

Exception object:06f1e5e4

Exception type: System.NullReferenceException

Message: Object reference not set to an instance of an object.

InnerException:

StackTrace (generated):

SP IP Function

02A0F950 0FE90F24 App_Code_wbwztx_4!Review.Finalize()+0x14

StackTraceString:

HResult: 80004003

Q:在什麼函數中異常被拋出?

A:在Review類中的finalizer/destructor 函數中。

Q:什麼對象正在被結束?注意:你可能實際經過二次拋出的異常已經獲得了信息,但經過 !pe original address 能獲得更清晰的信息。

AReview對象。

Q:正常狀況下,ASP.NET 拋出的異常會被全局(global)的異常處理或由錯誤頁面來顯示給用戶,但爲何這裏會發生呢?爲何會致使崩潰呢?

Aasp.net 的全局異常處理函數僅僅會處理在處理一個請求過程出現的異常。在這個地方,異常發生在finalizer中,意思是:沒有用戶看到這個異常,所以信息不能發送給任何人。

1.1 或者在2.0 中使用繼承原先的1.1 的方式,在finalizer中的異常不是致命的。它不會致使進程崩潰,而是finalizer的行爲會中止,這個是很是危險的,由於它意味着你沒有處理的代碼來釋放本地(原生,非託管)的資源,於是你會之內存泄露的方式來結束一段程序。這個是很是難找到的錯誤,數據庫鏈接等資源也會泄露。全部在finalizer線程中沒有處理的異常都必須認真研究和認真對待。

檢查代碼,確認狀況

1)打開Review.cs ,找到 銷燬/終結(destructor/finalizer)的代碼:

~Review()

{

if (quote.ToString() != string.Empty)

{

quote = null;

}

}

Q:哪一行的代碼或方法致使了異常?

A:在這個例子中代碼很簡單,也很容易準確的找到問題,quote.ToString()的那個判斷若是是if quote = null 則發生異常。

相關文章
相關標籤/搜索