• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看

      ?

      .Net應用異常處理研究

      2018-02-19 18:27:15葉信子
      機械制造 2018年12期
      關鍵詞:頂層線程調用

      □ 葉信子

      上海維宏電子科技股份有限公司 上海 200140

      1 .Net異常處理機制

      人們總是希望編寫出優(yōu)秀的代碼,以便在生產環(huán)境中穩(wěn)定而持久的運行。然而,不同的客戶所處的環(huán)境各不相同,很難保證代碼一直正確運行。因此,工程項目中,代碼的編寫需要更加注重穩(wěn)定性、容錯性和擴展性。

      一般而言,程序的容錯性主要體現在對于異常的處理上。應用程序拋出的異常,如果沒有得到及時的處理,公共語言運行庫(CLR)會自動停止該應用程序的運行。在處理異常的過程中,可以在線程中捕獲這個異常進行處理,然后繼續(xù)在另一個線程中重新拋出處理后的異常,以便堆棧的上一級繼續(xù)處理該異常。在異常發(fā)生時,CLR會在發(fā)生異常的堆棧上,由下往上依次查找對應類型異常的catch塊。如果找到了對應的catch塊,那么將異常交由該catch塊處理。處理完成后,應用程序繼續(xù)運行。否則,該異常將被視為未經處理的異常。CLR在任何地方檢測到未經處理的異常時,都會立即終止進程,導致應用程序崩潰。

      .Net標準的異常處理過程通常由try、catch、finally三個代碼塊完成,他們之間可以相互嵌套,組合起來處理系統(tǒng)的各種異常。

      2 代碼塊介紹

      2.1 try塊

      try塊是異常處理必需的代碼塊,這一代碼塊內部通常包含可能拋出異常的代碼。try塊還可以用來清理系統(tǒng)資源,使系統(tǒng)從異常中恢復過來。每個try塊后面必須跟有至少一個catch或finally塊。

      2.2 catch塊

      catch塊僅在對應的try塊拋出異常后才會執(zhí)行。若未發(fā)生任何異常,系統(tǒng)會跳過所有catch塊中的內容,繼續(xù)向下執(zhí)行。

      catch塊需要顯示所處理異常的類型。所有的異常均繼承自System.Exception。因此,catch塊后面的異常類型可以直接寫System.Exception。但是,為了能夠更好地處理不同類型的異常,仍然應該在catch塊后面放上具體的異常類型,以便CLR在異常發(fā)生后,能夠匹配到類型相同的catch塊執(zhí)行。

      2.3 finally塊

      finally塊中的內容,無論是否發(fā)生異常都會執(zhí)行。通常而言,finally塊中的代碼用來清理try塊中的資源。finally塊不是必需的,但如果需要用finally塊,那么其必須在所有的catch塊之后,并且一個try塊僅能有一個finally塊。

      總體而言,這三個代碼塊是.Net提供的異常處理機制的基礎。在try塊中嘗試執(zhí)行一些代碼。如果發(fā)生了錯誤,那么需要在catch塊中進行處理,以便從錯誤中恢復并繼續(xù)執(zhí)行。或者通過catch塊進行補償,來撤銷一些狀態(tài)更改,并向調用者上報錯誤。最終,通過finally塊確保清理操作無論如何都能執(zhí)行。

      3 在.Net中執(zhí)行非托管代碼

      .Net程序需要在CLR虛擬機中運行,屬于托管代碼。使用C或C++所編寫的組件,可以直接訪問和修改內存,屬于非托管代碼。托管代碼和非托管代碼的運行機制存在差異,導致非托管代碼無法在托管代碼中使用。因此.Net推出了P/Invoke機制,這實際上是一種函數調用機制,可以消除.Net托管代碼和非托管代碼之間的鴻溝。

      在.Net平臺開發(fā)出來前,在Windows平臺工作的程序員,基于Win32 API花費了大量精力編寫各種庫和com等非托管組件。為了避免程序重復,項目組一般通過P/Invoke直接在托管代碼中調用非托管DLL中的函數,提高工作效率,減少維護這部分功能的人力和時間成本。

      在設計.Net時,.Net團隊發(fā)現現有的Win32 API經過多年完善,規(guī)模實在過于龐大,導致.Net沒有為所有的Win32 API編寫基于.Net的托管實現文檔。而通過P/Invoke,則可以方便地使用較為完善的Win32 API函數。

      由于機制原因,托管代碼需要通過CLR間接訪問內存,因此,它的運行效率比非托管代碼稍低。在某些對效率要求較高的項目中,程序員通過C或C++編寫核心算法,并封裝成庫。在非托管代碼中,程序員可以通過P/Invoke直接調用,提升軟件的整體效率。

      在托管代碼中,需要通過調用函數,來執(zhí)行非托管代碼。這一過程主要有以下步驟:

      (1)獲得需要調用的非托管函數的信息,包括函數名、形參、返回值等內容;

      (2)在托管代碼中,聲明對應的非托管函數,并通過DLLImport特性,設置P/Invoke過程中所需要的屬性,主要為非托管庫的名稱、形參和返回值的內存布局方式;

      (3)在托管代碼中,直接調用聲明之后的非托管函數。

      實際執(zhí)行過程中,P/Invoke做了以下工作:

      (1)查找包含對應函數的DLL;

      (2)將對應的DLL裝載到內存中;

      (3)查找函數在內存中的地址,并將其參數推入堆棧,以便封送非托管函數所需的數據;

      (4)將控制權轉移給非托管函數,確認調用完成,非托管函數返回。

      CLR第一次調用函數時,會裝載對應的DLL,并查找函數的內存地址。當該函數發(fā)生第一次調用之后,CLR會將該函數的內存地址進行緩存,從而可以提高P/Invoke的使用效率。

      在應用程序被卸載之前,裝載過的非托管DLL會一直留在內存中。因此,在關閉軟件時,需要釋放非托管DLL申請的內存。

      4 .Net下未捕獲的異常處理

      隨著計算機技術的發(fā)展,軟件的規(guī)模日益擴大。在這樣的背景下,.Net技術雖然在各種大型軟件中應用越來越多,但是這些項目中不可避免地會存在許多第三方庫。

      在大型項目中,軟件的穩(wěn)定性是尤為重要的,因此,如何保證這些第三方庫能夠穩(wěn)定運行,是項目維護人員不得不面對的工作。所幸,.Net平臺有一套完善且強大的異常處理機制。上述異常處理機制在通過.Net直接操作內存的過程中即使產生越界和內存泄漏,也有較為有效的解決措施。因此,大部分通過.Net技術搭建的軟件穩(wěn)定性是有保證的。

      但是,代碼如果沒有通過CLR運行,而是直接通過P/Invoke機制調用C或C++庫操作內存而產生了異常,那么上述.Net框架提供的異常處理機制將無法進行工作,導致應用程序運行出錯,甚至崩潰。

      有兩種情況無法通過這種方法捕獲。

      (1)垃圾回收時產生的異常。這種異常一般在Finalize函數中被拋出,但是沒有被捕獲處理。除了這種情況,類似內存耗盡時,也會造成系統(tǒng)產生未經處理的異常,導致應用程序崩潰。

      (2)主線程無法捕獲的未處理異常。通常會在應用程序的入口中添加try塊、catch塊來處理程序運行時產生的所有異常,但是應用程序在調用外部組件提供的接口函數或者Win32提供的某些API時,在這些組件內部產生了異常,這些異常無法直接被主線程中的try塊、catch塊捕獲。

      因為有上述兩種情況,所以try塊、catch塊是無法捕獲所有異常的。由此可見,即使代碼中所有可能出現問題的地方都加上了try塊、catch塊,也無法杜絕未經捕獲的異常導致應用程序崩潰。因此,要提高程序的健壯性和可維護性,使應用程序能夠長時間穩(wěn)定運行,軟件工程師需要一種用能截獲未經處理異常的機制,來幫助應用程序從異常中恢復,或者記錄有價值的錯誤信息。

      在非托管代碼中,異常的處理會經過以下步驟。

      (1)調試器處理。異常發(fā)生的時候,如果程序正在被調試,那么異常會被交給調試器。調試器收到異常后,判斷該異常是否需要處理。

      (2)執(zhí)行VEH。異常發(fā)生時,如果應用程序不在調試過程中,或者調試器此時返回值為0,那么操作系統(tǒng)會將該異常交給VEH處理。VEH是一個鏈表,可以掛接多個VEH的處理過程,在系統(tǒng)調用時,按順序調用鏈表中的多個函數,依次處理異常。

      VEH的返回值有三個:1、0、-1。返回1時,表示無效的處理,實際處理同0。返回0時,將把異常交給VEH鏈表中的下一個進行處理。返回-1時,表示異常已處理完成,此時系統(tǒng)會退出異常處理器,在異常指令處繼續(xù)往下執(zhí)行。

      (3)執(zhí)行SEH。當所有VEH執(zhí)行完成后,異常會被SEH處理。SHE基于線程棧的異常處理機制,僅處理自身線程內部發(fā)生的異常。

      (4)頂層異常處理。頂層異常處理實際也是通過SEH實現的。在最頂層的SEH中,可以注冊一個頂層異常處理器,它可以處理所有線程拋出的異常。因此,SEH發(fā)現無法處理的異常時,會檢查是否注冊了頂層異常處理,如果注冊了,則調用頂層異常處理。

      .Net中,提供了Unhandled Exception Event Handler事件,這一事件可以注冊到頂層異常處理中。通過這一事件,可以截獲系統(tǒng)中未捕獲的異常,并進行處理。

      Unhandled Exception Event Handler的事件參數Unhandled Exception Event Argse具體有兩個屬性,分別為 Exception Object和 Is Terminating。Is Terminating表示如果異常不處理,是否會終止當前應用程序。Exception Object為截獲異常的對象。當系統(tǒng)捕獲到未經處理的異常時,通過該對象就可以記錄異常在何處被引發(fā)。通過這一信息,軟件設計人員可以在操作該對象的地方做出改進,降低異常發(fā)生的可能性。此外,依賴這一事件,可以在程序崩潰退出之前,做好數據備份,記錄錯誤日志工作,以便排查問題。

      5 抓取Dump加固程序

      在頂層異常處理中,可以記錄下程序的Dump文件,保存未處理異常現場,以便后續(xù)分析和改進。

      在應用程序中掛接Unhandled Exception事件。事件的響應函數中,構建描述Mini Dump信息的結構體Mini Dump Exception Information,然后通過Marshal.Get Exception Pointers函數獲取異常的位置,通過Win32 API的Get Current Thread Id函數獲取當前的非托管線程號。最后,通過Windbg的Dbghelp.dll中提供的Mini Dump Write Dump函數,將當前應用程序的信息寫入對應的文件中,形成一個Dump文件。

      在程序發(fā)生異常崩潰時,通過Dump文件,可以分析程序崩潰時的CallStack。配合應用程序對應的Pdb文件和源碼,可以在程序崩潰后繼續(xù)調試當前異常。

      猜你喜歡
      頂層線程調用
      汽車頂層上的乘客
      文苑(2019年24期)2020-01-06 12:06:58
      核電項目物項調用管理的應用研究
      LabWindows/CVI下基于ActiveX技術的Excel調用
      測控技術(2018年5期)2018-12-09 09:04:46
      淺談linux多線程協(xié)作
      基于系統(tǒng)調用的惡意軟件檢測技術研究
      頂層設計
      加快頂層設計
      健康卡“卡”在頂層沒聯(lián)網
      利用RFC技術實現SAP系統(tǒng)接口通信
      Linux線程實現技術研究
      乐亭县| 沙洋县| 喀喇沁旗| 紫金县| 孟津县| 四川省| 酒泉市| 保定市| 宁蒗| 长泰县| 新竹县| 密山市| 色达县| 于都县| 常宁市| 曲麻莱县| 仲巴县| 阿拉善右旗| 荆州市| 响水县| 辽宁省| 宾阳县| 南开区| 仁怀市| 门源| 太仆寺旗| 常宁市| 兴海县| 涞源县| 额尔古纳市| 庆云县| 平乡县| 醴陵市| 互助| 喀喇| 通化县| 荥阳市| 崇明县| 保山市| 东源县| 利川市|