Windows系列作業系統平台中所提供的異常處理機制

來源:互聯網
上載者:User

轉載自-http://blog.programfan.com/article.asp?id=9836

大家現在知道,在C++中有完善的異常處理機制,同樣在C語言中也有很不錯的異常處理機制來支援,另外在其它許多現代程式設計語言中,也都有各自的異常處理編程機制,如Ada語言等。那麼為什麼現在此處還在討論,作業系統平台中所提供的異常處理機制呢?這是因為在許多系統中,程式設計語言所提供的異常處理機制的實現,都是建立在作業系統中所提供的異常處理機制之上,如Windows平台上的VC編譯器所實現的C++異常處理模型,它就是建立在SEH機制之上的,在“愛的秘密”篇中,探討VC中異常處理模型實現的時候,會進行更深入的研究和分析。另外,當然也有其它的系統,如Linux作業系統上的gcc就沒有採用到作業系統中所提供的異常處理機制。但是這樣會有一個很大的缺點,那就是對於應用程式的開發人員而言,它不能夠很好在自己的應用程式中,來有效控制作業系統中所出現的一些意外的系統異常,例如程式執行過程中可能出現的段錯誤,被0除等計算異常,以及其它許多不同類型的系統異常等。所以Linux作業系統上的gcc編譯的程式中,它只能捕獲程式中,曾經被自己顯式地throw出來的異常,而對於系統異常,catch block是毫無辦法的。

  因此,作業系統平台中所提供的異常處理機制是非常有必要的。而且,異常處理機制的實現也是作業系統設計時的一個重要課題。通常,類Unix作業系統所提供的異常處理機制是大家非常熟悉的,那就是作業系統中的訊號量處理(Signal Handling),好像這也應該是Posix標準所定義異常處理介面,因此Window系列作業系統平台也支援這種機制,“訊號量處理”編程機制也會在後面的章節中進一步深入討論。而現在(以及在接下來的幾篇文章中),將全面闡述Window系列作業系統平台提供的另外一種更完善的異常處理機制,那就是大名鼎鼎的結構化異常處理(Structured Exception Handling,SEH)的編程方法。

SEH設計的主要動機

  下面是出自《Window核心編程》中一小段內容的引用:

  “微軟在Windows中引入SEH的主要動機是為了便於作業系統本身的開發。作業系統的開發人員使用SEH,使得系統更加強壯。我們也可以使用SEH,使我們的自己的程式更加強壯。使用SEH所造成的負擔主要由編譯器來承擔,而不是由作業系統承擔。當異常塊(exception block)出現時,編譯器要產生特殊的代碼。編譯器必須產生一些表( t a b l e)來支援處理SEH的資料結構。編譯器還必須提供回調( c a l l b a c k)函數,作業系統可以調用這些函數,保證異常塊被處理。編譯器還要負責準備棧結構和其他內部資訊,供作業系統使用和參考。在編譯器中增加SEH支援不是一件容易的事。不同的編譯器廠商會以不同的方式實現SEH,這一點並不讓人感到奇怪。幸虧我們可以不必考慮編譯器的實現細節,而只使用編譯器的SEH功能。”

  的確,SEH設計的主要動機就是為了便於作業系統本身的開發。為什麼這麼說呢?這是因為作業系統是一個非常龐大的系統,而且它還是處於電腦整個系統中,非常底層的系統軟體,所以要求“作業系統”這個關鍵的系統軟體必須要非常強壯,可靠性非常高。當然提升作業系統軟體的可靠性有許多有效方法,例如嚴謹的設計,全面而科學的測試。但是俗話說得好,“智者千慮,必有一失”。因此在編程代碼中,有一個非常有效異常處理機制,將大大提高軟體系統的可靠性。說道這裡,也許很多朋友們說:“阿愚呀!你有沒有搞錯,無論是C++還是C語言中,不都有很好的異常處理機制嗎?為什麼還需要另外再設計一種呢?”。的確沒錯,但是請注意,作業系統由於效率的考慮,它往往不會考慮採用C++語言來編寫,它大部分模組都是採用C語言來編碼的,另外還包括一小部分的彙編代碼。所以,這樣作業系統中最多隻能用goto語句,以及setjmp和longjmp等機制。但Window的設計者認為這遠遠不夠他們的需要,離他們的要求相差甚遠。而且,尤其是在作業系統中,最大的軟體模組就是裝置的驅動程式了,而且裝置的驅動程式模組中,其中的又有絕大部分是由第3方(硬體供應商)來開發的。這些第3方開發的驅動程式模組,與作業系統核心關聯緊密,它將嚴重影響到整個作業系統的可靠性和穩定性。所以,如何來促使第3方開發的驅動程式模組變得更加可靠呢?它至少不會影響到作業系統核心的正常工作,或者說甚至導致作業系統核心的崩潰。客觀地說,這的確很難做得到,因為自己的命運掌握在別人手裡了。但是Window的設計者想出了一個很不錯的方法,那就是為第3方的驅動程式開發人員提供SEH機制,來最大程度上提升第3方開發出的驅動程式的可靠性和穩定性。相信有過在Windows平台上開發過驅動程式的朋友們對這一點深有感觸,而且有關驅動程式開發的大多數書籍中,都強烈建議你在編程中使用SEH機制。

   現在來談談為什麼說,C語言中的setjmp和longjmp機制沒有SEH機制好呢?呵呵!當然在不深入瞭解SEH機制之前,來討論並很好地解釋清楚這個問題也許是比較困難的。但是主人公阿愚卻認為,這裡討論這個問題是最恰當不過的了。因為這樣可以很好地沿著當年的SEH的設計者們的足跡,來透析他們的設計思想。至少我們現在可以充分地分析setjmp和longjmp機制的不足之處。例如說,在實際的編程中(尤其是系統方面的編程),是不是經常遇到這種狀況,範例程式碼如下:

#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>

jmp_buf mark;

void test1()
{
char* p1, *p2, *p3, *p4;
p1 = malloc(10);
if (!p1) longjmp(mark, 1);

p2 = malloc(10);
if (!p2)
{
// 這裡雖然可以釋放資源,
// 但是程式員很容易忘記,也容易出錯
free(p1);
longjmp(mark, 1);
}

p3 = malloc(10);
if (!p3)
{
// 這裡雖然可以釋放資源
// 但是程式員很容易忘記,也容易出錯
free(p1);
free(p2);
longjmp(mark, 1);
}

p4 = malloc(10);
if (!p4)
{
// 這裡雖然可以釋放資源
// 但是程式員很容易忘記,也容易出錯
free(p1);
free(p2);
free(p3);
longjmp(mark, 1);
}

// do other job

free(p1);
free(p2);
free(p3);
free(p4);
}

void test()
{
char* p;
p = malloc(10);

// do other job

test1();

// do other job

// 這裡的資源可能得不到釋放
free(p);
}

void main( void )
{
int jmpret;

jmpret = setjmp( mark );
if( jmpret == 0 )
{
char* p;
p = malloc(10);

// do other job

test1();

// do other job
// 這裡的資源可能得不到釋放
free(p);
}
else
{
printf("捕獲到一個異常/n");
}
}

  上面的程式很容易導致記憶體資源泄漏,而且程式的代碼看上去也比較彆扭。程式員編寫代碼時,總要非常地小心翼翼地釋放相關的資源。有可能一個稍微的處理不當,就可能導致資源泄漏,甚至更嚴重的是引發系統的死結,因為在編寫驅動程式時,畢竟與一般的應用程式有很大的不同,會經常使用到進程間的一些同步和互斥控制等。

  怎麼辦?如果有一種機制,在程式中出現異常時,能夠給程式員一個恰當的機會,來釋放這些系統資源,那該多好呀!其實這種需求有點相當於C++中的解構函式,因為它不管何種情況下,只要對象離開它生存的範圍時,它總會被得以執行。但是在C語言中的setjmp和longjmp機制,卻顯然做不到這一點。SEH的設計者們考慮到了這一點,因此在SEH機制中,它提供了此項功能給程式開發人員。這其實也是SEH中最強大,也最有特色的地方。另外,SEH還提供了程式出現異常後,有效地被得以恢複,程式繼續執行的機制,這也是其它異常處理模型沒有的(雖然一般情況下,沒有必要這樣做;但是對於系統模組,有時這是非常有必要的)。

SEH究竟何物?

  首先還是引用MSDN中關於SEH的有關論述,如下:

Windows 95 and Windows NT support a robust approach to handling exceptions, called structured exception handling, which involves cooperation of the operating system but also has direct support in the programming language.
An “exception” is an event that is unexpected or disrupts the ability of the process to proceed normally. Exceptions can be detected by both hardware and software. Hardware exceptions include dividing by zero and overflow of a numeric type. Software exceptions include those you detect and signal to the system by calling the RaiseException function, and special situations detected by Windows 95 and Windows NT.
You can write more reliable code with structured exception handling. You can ensure that resources, such as memory blocks and files, are properly closed in the event of unexpected termination. You can also handle specific problems, such as insufficient memory, with concise, structured code that doesn’t rely on goto statements or elaborate testing of return codes.
Note These articles describe structured exception handling for the C programming language. Although structured exception handling can also be used with C++, the new C++ exception handling method should be used for C++ programs. See Using Structured Exception Handling with C++ for information on special considerations.

  我們雖然都知道,SEH是Window系列作業系統平台提供的一種非常完善的異常處理機制。但這畢竟有些過於抽象了點,對於程式員而言,它應該有一套類似於像C++中那樣的try,catch,throw等幾個關鍵字組成的完整的異常處理模型。是的,這的確沒錯,SEH也有類似的文法,那就是它由如下幾個關鍵字組成:
__try
__except
__finally
__leave

  呵呵!這是不是很多在Windows平台上做開發的程式員朋友們都用過。很熟悉吧!但是這裡其實有一個認識上的誤區,大多數程式員,包括很多電腦書籍中,都把SEH機制與__try,__except,__finally,__leave異常模型等同起來。這種提法是不對的,至少是不準確的。因為SHE狹義上講,只能算是Window系列作業系統所提供的一種異常處理機制;而無論是__try,__except,__finally,__leave異常模型,還是try,catch,throw異常模型,它們都是VC所實現並提供給開發人員的。其中__try,__except,__finally,__leave異常模型主要是提供給C程式員使用;而try,catch,throw異常模型,它則是提供給C++程式員使用,而且它也遵循C++標準中異常模型的定義。這多種異常機制之間的關係如所示:

總結

  為了更進一步認識SEH機制,認識SEH與__try,__except,__finally,__leave異常模型機制的區別。下一篇文章中,主人公阿愚還是拿出一個具體的例子程式來與大家一起分享。注意,它那個例子中,它既沒有使用到__try,__except,__finally,__leave異常模型;也沒有利用到try,catch,throw異常模型。它直接使用到Windows作業系統所提供的SEH機制,並完成一個簡單的封裝。繼續吧!GO!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.