首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

.NET 4.0 新特性:Corrupted State Exceptions(程序狀態損毀例外)

     編輯:關於.NET

許多開發者習慣寫 catch (Exception e) { /* 吞掉所有例外 */ },無論為了不讓使用者看到錯誤、或讓程式繼續跑。但在微軟眼中,這對嚴重例外(如存取違規)是危險的——特別當你的程式作為外掛寄宿在 VS、Office 等進程中時,嚴重例外應讓進程終止,而非繼續執行導致更大災難。.NET 4.0 引入 Corrupted State Exceptions (CSE) 機制,由 CLR 統一攔截處理這類「可能導致進程崩潰」的例外,不再交給使用者程式碼。

為何需要 CSE?

  • 輕微例外(如字串為空):使用者輸入問題,不會導致進程崩潰,可捕獲處理。
  • 嚴重例外(如 AccessViolationException):記憶體損毀、堆疊溢位等,通常意味著進程狀態已不可預測,繼續執行極可能造成資料損毀或連帶崩潰宿主進程(如 Outlook、IE)。

.NET 4.0 前,CLR 將所有例外(含 COM/Win32 例外)一律拋給使用者程式碼。許多開發者為避免客訴,濫用 catch (Exception) 吞掉一切,導致嚴重例外被隱藏,最終讓作業系統或宿主應用程式背負「不穩定」罵名。

CLR 如何處理 CSE?

.NET 4.0 起,CLR 將特定嚴重例外標記為 CSE(如繼承自 SystemException 的 AccessViolationException),並判斷拋出來源:

  • 作業系統/執行階段拋出(如硬體存取違規)→ 視為 CSE,CLR 自行處理(終止進程、顯示 Watson 對話框),不進入使用者 catch 區塊。
  • 使用者程式碼主動拋出(throw new AccessViolationException())→ CLR 認為開發者知情且可控,正常拋給使用者 catch。

範例 1:系統拋出的存取違規

unsafe static void T2() {
    try {
        int* pd = stackalloc int[1];
        pd[1911] = 2;          // 故意越界寫入
        Console.WriteLine(pd[1111]);
    } catch (Exception e) {
        Console.WriteLine(e);  // 不會執行到這裡!
    }
}

結果:程式直接終止,CLR 顯示未處理的 AccessViolationException,catch 區塊完全被繞過。

範例 2:使用者主動拋出同類型例外

static void T3() {
    try {
        throw new AccessViolationException(); // 使用者代碼拋出
    } catch (Exception e) {
        Console.WriteLine(e);  // 正常進入 catch,程式繼續執行
    }
}

結果:catch 正常捕獲,程式不中斷。

如何繼續捕獲 CSE?(兩種相容方式)

1. 既有程式不想改碼、重新編譯

在 app.config 加入:

<configuration>
  <runtime>
    <legacyCorruptedStateExceptionsPolicy enabled="true" />
  </runtime>
</configuration>

或直接在 .NET 4.0 上執行舊版編譯好的組件(CLR 自動啟用舊行為)。

2. 新程式需自行處理 CSE

使用 System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute 標記方法:

[HandleProcessCorruptedStateExceptions]
public static int Main() {
    try {
        CallMainProgramLoop();
    } catch (Exception e) { // 此處可捕獲 CSE
        Console.WriteLine(e.Message);
        return 1; // 記錄後優雅退出
    }
    return 0;
}

限制:此屬性只能套用在方法上。

總結

微軟引入 CSE 是為了阻止「吞掉嚴重例外」的惡習,強迫開發者區分可復原與不可復原錯誤。雖提供相容管道,但最佳實務仍是:只捕獲明確知道如何處理的具體例外類型,讓嚴重錯誤正確終止進程,避免擴大損害。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved