日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

异常处理与MiniDump详解(3) SEH(Structured Exception Handling)

發布時間:2023/11/27 生活经验 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 异常处理与MiniDump详解(3) SEH(Structured Exception Handling) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

?

write by?九天雁翎(JTianLing) -- blog.csdn.net/vagrxie

討論新聞組及文件

一、???綜述

SEH--Structured Exception Handling,是Windows操作系統使用的異常處理方式。

對于SEH,有點需要說明的是,SEH是屬于操作系統的特性,不為特定語言設計,但是實際上,作為操作系統的特性,幾乎就等同與面向C語言設計,這點很好理解,就像Win32 API,Linux下的系統調用,都是操作系統的特性吧,實際還是為C做的。但是,作為為C語言設計的東西,實際上可調用的方式又多了,匯編,C++對于調用C語言的接口都是比較方便的。

?

二、???基礎篇

還是簡單介紹一下SEH的使用,但是不準備太詳細的介紹了,具體的詳細介紹見參考中提及的書目。關于SEH的基本應用,《Windows核心編程》絕對是最佳讀物(其實個人一直認為《Windows核心編程》是Windows編程領域必看的第二本書,第一本是《Programming Windows》。關于SEH更深入的一點的知識可能就要參考一些能用匯編講解的書籍了,《Windows用戶態程序高效排錯》算是其中講的不錯的一本。

首先,SEH也有像C++異常一樣的語法,及類try-catch語法,在SEH中為__try-except語法,拋出異常從throw改為RaiseException,在MSDN中的語法描述為:

__try?

{

???// guarded code

}

__except (?expression?)

{

???// exception handler code

}

?

見一個實際使用的例子:

例1:

#include?<iostream>

#include?<windows.h>

using?namespace?std;

?

int?main()

{

????__try

????{

???????RaiseException(0, 0, 0,?NULL);

????}

????__except(EXCEPTION_EXECUTE_HANDLER)

????{

???????cout?<<"Exception Raised."?<<endl;

?

????}

?

????cout?<<"Continue running"?<<endl;

}

?

這可能是最簡單的SEH的例子了,輸出如下:

Exception Raised.

Continue running

?

這個例子和普通C++異常的try-catch類似,也很好理解。只不過catch換成了except。

因為C語言沒有智能指針,那么就不能缺少finally的異常語法,與JAVA,Python等語言中的也類似,(這是C++中沒有的)finally語法的含義就是無論如何(不管是正常還是異常),此句總是會執行,常用于資源釋放。

?

例2:

?

#include?<iostream>

#include?<windows.h>

using?namespace?std;

?

int?main()

{

????__try

????{

?

???????__try

???????{

???????????RaiseException(0, 0, 0,?NULL);

???????}

???????__finally

???????{

???????????cout?<<"finally here."?<<endl;

?

???????}

????}

????__except(1)

????{

?

????}

?

????__try

????{

?

???????__try

???????{

???????????int?i;

???????}

???????__finally

???????{

???????????cout?<<"finally here."?<<endl;

?

???????}

????}

????__except(1)

????{

?

????}

????cout?<<"Continue running"?<<endl;

????getchar();

}

?

這個實例看起來過于奇怪,因為沒有將各個try-finally放入獨立的模塊之中,但是說明了問題:

  1. finally的語句總是會執行,無論是否異常finally here總是會輸出。
  2. finally僅僅是一條保證finally語句執行的塊,并不是異常處理的handle語句(與except不同),所以,假如光是有finally語句塊的話,實際效果就是異常會繼續向上拋出。(異常處理過程也還是繼續)
  3. finally執行后還可以用except繼續處理異常,但是SEH奇怪的語法在于finally與except無法同時使用,不然會報編譯錯誤。

如下例:

????__try

????{

???????RaiseException(0, 0, 0,?NULL);

????}

????__except(1)

????{

?

????}

????__finally

????{

???????cout?<<"finally here."?<<endl;

?

????}

?

VS2005會報告

error C3274: __finally?沒有匹配的try

這點其實很奇怪,難道因為SEH設計過于老了?-_-!因為在現在的語言中finally都是允許與except(或類似的塊,比如catch)同時使用的。C#,JAVA,Python都是如此,甚至在MS為C++做的托管擴展中都是允許的。如下例:(來自MSDN中對finally keyword [C++]的描述)

using?namespace?System;

?

ref?class?MyException:?public?System::Exception{};

?

void?ThrowMyException() {

????throw?gcnew?MyException;

}

?

int?main() {

????try?{

???????ThrowMyException();

????}

????catch?(?MyException^?e?) {

???????Console::WriteLine(??"in catch"?);

???????Console::WriteLine(?e->GetType() );

????}

????finally?{

???????Console::WriteLine(??"in finally"?);

????}

}

?

當你不習慣使用智能指針的時候常常會覺得這樣會很好用。關于finally異常語法和智能指針的使用可以說是各有長短,這里提供劉未鵬的一種解釋,(見參考5的RAII部分,文中比較的雖然是JAVA,C#,但是實際SEH也是類似JAVA的)大家參考參考。

?

SEH中還提供了一個比較特別的關鍵字,__leave,MSDN中解釋如下

Allows for immediate termination of the __try block without causing abnormal termination and its performance penalty.

簡而言之就是類似goto語句的拋出異常方式,所謂的沒有性能損失是什么意思呢?看看下面的例子:

#include?<iostream>

#include?<windows.h>

using?namespace?std;

?

int?main()

{

????int?i?= 0;

????__try

????{

???????__leave;

???????i?= 1;

????}

????__finally

????{

???????cout?<<"i: "?<<i?<<" finally here."?<<endl;

????}

?

?

????cout?<<"Continue running"?<<endl;

????getchar();

}

?

?

輸出:

i: 0 finally here.

Continue running

實際就是類似Goto語句,沒有性能損失指什么?一般的異常拋出也是沒有性能損失的。

MSDN解釋如下:

The __leave keyword

The __leave keyword is valid within a try-finally statement block. The effect of __leave is to jump to the end of the try-finally block. The termination handler is immediately executed. Although a goto statement can be used to accomplish the same result, a goto statement causes stack unwinding. The __leave statement is more efficient because it does not involve stack unwinding.

?

意思就是沒有stack unwinding,問題是。。。。。。如下例,實際會導致編譯錯誤,所以實在不清楚到__leave到底干啥的,我實際中也從來沒有用過此關鍵字。

?

#include?<iostream>

#include?<windows.h>

using?namespace?std;

?

?

void?fun()

{

????__leave;

}

?

int?main()

{

????__try

????{

???????fun();

????}

????__finally

????{

???????cout?<<" finally here."?<<endl;

????}

?

?

????cout?<<"Continue running"?<<endl;

????getchar();

}

?

三、???提高篇

1.??????SEH的優點

1)????一個很大的優點就是其對異常進程的完全控制,這一點是C++異常所沒有的,因為其遵循的是所謂的終止設定。

這一點是通過except中的表達式來控制的(在前面的例子中我都是用1表示,實際也就是使用了EXCEPTION_EXECUTE_HANDLER方式。

EXCEPTION_CONTINUE_EXECUTION (–1)???表示在異常發生的地方繼續執行,表示處理過后,程序可以繼續執行下去。?C++中沒有此語義。

EXCEPTION_CONTINUE_SEARCH (0)???異常沒有處理,繼續向上拋出。類似C++的throw;

EXCEPTION_EXECUTE_HANDLER (1)??異常被處理,從異常處理這一層開始繼續執行。?類似C++處理異常后不再拋出。

?

?

2)????操作系統特性,不僅僅意味著你可以在更多場合使用SEH(甚至在匯編語言中使用),實際對異常處理的功能也更加強大,甚至是程序的嚴重錯誤也能恢復(不僅僅是一般的異常),比如,除0錯誤,訪問非法地址(包括空指針的使用)等。這里可以用一個例子來說明:

#include?<iostream>

#include?<windows.h>

using?namespace?std;

?

?

?

int?main()

{

????__try

????{

???????int?*p?=?NULL;

???????*p?= 0;

????}

????__except(1)

????{

???????cout?<<"catch that"?<<endl;

????}

?

?

????cout?<<"Continue running"?<<endl;

????getchar();

}

?

輸出:

catch that

Continue running

在C++中這樣的情況會導致程序直接崩潰的,這一點好好利用,可以使得你的程序穩定性大增,以彌補C++中很多的不足。但是,問題又來了,假如異常都被這樣處理了,甚至沒有聲息,非常不符合發生錯誤時死的壯烈的錯誤處理原則。。。。。。。很可能導致程序一堆錯誤,你甚至不知道為什么,這樣不利于發現錯誤。

但是,SEH與MS提供的另外的特性MiniDump可以完美的配合在一起,使得錯誤得到控制,但是錯誤情況也能捕獲到,稍微的緩解了這種難處(其實也說不上完美解決)。

這一點需要使用者自己權衡,看看到底開發進入了哪個階段,哪個更加重要,假如是服務器程序,那么在正式跑著的時候,每崩潰一次就是實際的損失。。。所以在后期可以考慮用這種方式。

關于這方面的信息,在下一次在詳細講解。

?

2.??????SEH的缺點

其實還是有的,因為是為操作系統設計的,實際類似為C設計,那么,根本就不知道C++中類/對象的概念,所以,實際上不能識別并且正確的與C++類/對象共存,這一點使用C++的需要特別注意,比如下例的程序根本不能通過編譯。

例一:

int?main()

{

????CMyClass?o;

????__try

????{

????}

????__except(1)

????{

???????cout?<<"catch that"?<<endl;

????}

?

?

????cout?<<"Continue running"?<<endl;

????getchar();

}

?

例二:

?

int?main()

{

????__try

????{

???????CMyClass?o;

????}

????__except(1)

????{

???????cout?<<"catch that"?<<endl;

????}

?

?

????cout?<<"Continue running"?<<endl;

????getchar();

}

?

?

錯誤信息都為:

warning C4509:?使用了非標準擴展:“main”使用SEH,并且“o”有析構函數

error C2712:?無法在要求對象展開的函數中使用__try

這點比較遺憾,但是我們還是有折衷的辦法的,那就是利用函數的特性,這樣可以避開SEH的不足。

比如,希望使用類的使用可以這樣:

這個類利用了上節的CResourceObserver類,

class?CMyClass?:?public?CResourceObserver<CMyClass>

{

?

};

?

void?fun()

{

????CMyClass?o;

}

?

?

#include?<iostream>

#include?<windows.h>

using?namespace?std;

?

?

int?main()

{

????__try

????{

???????fun();

????}

????__except(1)

????{

???????cout?<<"catch that"?<<endl;

????}

?

?

????cout?<<"Continue running"?<<endl;

????getchar();

}

?

?

輸出:

class CMyClass Construct.

class CMyClass Deconstruct.

Continue running

可以看到正常的析構,簡而言之就是將實際類/對象的使用全部放進函數中,利用函數對對象生命周期的控制,來避開SEH的不足。

?

?

四、???參考資料

  1. Windows核心編程(Programming Applications for Microsoft Windows),第4版,Jeffrey Richter著,黃隴,李虎譯,機械工業出版社
  2. MSDN—Visual Studio 2005?附帶版,Microsoft
  3. 加密與解密,段鋼編著,電子工業出版社
  4. Windows用戶態程序高效排錯,熊力著,電子工業出版社

5.?錯誤處理(Error-Handling):為何、何時、如何(rev#2),劉未鵬(pongba)著

?

?

??

write by?九天雁翎(JTianLing) -- blog.csdn.net/vagrxie

轉載于:https://www.cnblogs.com/lehoho/p/9364966.html

總結

以上是生活随笔為你收集整理的异常处理与MiniDump详解(3) SEH(Structured Exception Handling)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。