異常與除錯是緊密相連的。
異常記錄:
1.要記錄異常資訊
2.異常是什麼型別
3.異常是在什麼位置發生的
異常的分發:
上面的資訊記錄下來以後,尋找處理異常的函式。
這個過程為異常的分發
異常處理:
最後找到異常處理函式並呼叫(異常處理)
異常記錄,異常分發,異常處理。
異常的分類:
(本質上大體的分類)
1.cpu產生的異常
一定是cpu發現的
2.軟體模擬產生的異常
高階語言模擬產生的異常
cpu異常的產生:
cpu指令檢測到異常(例如:除0) --> 查idt表,執行中斷處理函式 --> commondispatchexception(把異常相關的資訊存到乙個結構體) --> kidispatchexception
(3環進0環,先儲存現場)
異常資訊儲存到了下面這個結構體裡面:
typedef struct _exception_record exception_record;
exceptionflags:
cpu產生的異常,這個值是0,軟體產生的異常,這裡存的值是1
_exception_record *exceptionrecord:
通常是空的,出現巢狀異常的情況下,就是這個異常的處理程式執行的時候,又發生異常了,會通過這個指標指向下乙個異常。
dword numberparameters; //附加引數個數
ulong_ptr exceptioninformation[exception_maximum_parameters]; //附加引數指標
用來進一步描述異常的資訊,用的不多。
在上面那個除0異常例子中:
commondispatchexception(它要做的事就事把這些值存到在堆疊中構建的結構體)的反彙編中
mov ebx,[ebp+68h]:
[ebp+68h]指向的是eip,eip記錄的就是異常發生的位址exceptionaddress
mov eax,0c0000094h:
0c0000094h代表的是異常的型別,不同的異常有不同的值,這個值是微軟定義的。
總結:cpu異常執行的流程:
1.cpu指令檢測到異常
2.查idt表,執行中斷處理程式(它並不會直接處理異常,把機會先留給程式設計師了)
3.呼叫commondispatchexception(構建exception_record)
4.kidispatchexception(分發異常:目的找到異常處理的函式)
模擬異常的產生:
cxxthrowexception -->
(kernel32.dll)raiseexception(dword dwexceptioncode,dword dwexceptionflags,dword nnumberofarguments,const ulong_ptr *lparfuments) -->
ntdll.dll!rtlraiseexception() -->
nt!ntraiseexception -->
nt!kiraiseexception
(kernel32.dll)raiseexception分析:
1.將引數中的值填充到exception_record這個結構體中
typedef struct _exception_record
exception_record;
與cpu異常產生流程的兩點不同:
1.cpu中exceptioncode每種不同型別的異常,都對應不同的32位的值。軟體模擬異常中的exceptioncode 和當前的編譯環境有關。相同編譯環境下的值也是相同的。
2.cpu中exceptionaddress異常會記錄異常的位置,記錄的是真正的異常時**發生的。軟體模擬異常中的exceptionaddress 儲存的是乙個固定的值,而這個值是raiseexception 這個函式的位址。
kiraiseexception分析:
1.exception_record.exceptioncode 最高位清0(目的是區分cpu異常與軟體模擬異常)
2.呼叫kidispatchexception ,開始分發異常
異常機制與函式呼叫區別和聯絡
在查詢用來處理被丟擲異常的 catch 子句時因為異常而退出,復合語句和函式定義這個過程被稱作 棧展開stack unwinding 隨著棧的展開在退出的復合語句和函式定義中 宣告的區域性變數的生命期也結束了。c 保證隨著棧的展開儘管區域性類物件的生命期是因為丟擲異常而被結束但是這些區域性類物件的析...
C 異常的幕後10 Unwind 與呼叫幀資訊
nicolasbrailo 我們讓我們的小abi專案 鏈結 能夠丟擲異常了,現在我們著力捕捉它們 上次我們實現了乙個能夠檢測並處理異常的personality函式,不過它仍然有點不完整 即使它能正確地通知棧回滾器它何時應該停止,但我們版本的 gxx personality v0不能執行catch塊裡...
丟擲異常與傳引數及呼叫虛函式之間的區別與聯絡
先來談談丟擲異常與傳參 聯絡 都有三種傳遞方式 值傳遞 引用 指標 區別 1.傳遞引數,最終控制權會回到呼叫處。而丟擲異常,則不會回到拋出處。2.傳遞引數所允許的隱式型別轉換比丟擲異常要多。異常只允許兩種隱式型別轉換 1 將基類轉換成派生類物件,即可用捕捉派生類異常。2 將 有型指標 轉換成 無形指...