2015-01-15 34 views
3

背景CLR如何識別「腐敗狀態異常」?

我們的應用程序調用一個混合模式組件,其具有在它的非託管代碼已知的錯誤導致的AccessViolationException被拋出。

我們的目標是在我們終止應用程序之前,捕獲AV異常並將其包裝並拋出一個新的異常,這個異常會在堆棧中被更高地捕獲並記錄下來。

問題

我們的代碼並沒有表現得如我們預期......我們用來包裹的表現就像它的AV例外是CSE的「香草」的例外,並沒有因我們的頂級抓級別的異常處理程序。相反,它冒泡到了操作系統,終止了這個過程。這隻會在Windows事件日誌中留下令人困惑的日誌消息,表明InvalidOperationException已經設法繞過所有異常處理程序並終止進程。

請注意,此行爲僅在AV異常設置爲包裝異常上的內部異常時纔會顯示。

下面是一個例子:

[Test] 
    public void RunTest() 
    { 
     try 
     { 
      ProvokeAccessViolation(); 
     } 
     catch (InvalidOperationException e) 
     { 
      // We never get here! 
      Console.WriteLine("Log exception: " + e); 
     } 
    } 

    [HandleProcessCorruptedStateExceptions] 
    [SecurityCritical] 
    public static void ProvokeAccessViolation() 
    { 
     try 
     { 
      var ptr = new IntPtr(1); 
      const bool someValue = true; 
      Marshal.StructureToPtr(someValue, ptr, true); // Will throw AccessViolationException 
     } 
     catch (AccessViolationException ex) 
     { 
      Console.WriteLine("Caught AV exception: " + ex); 
      throw new InvalidOperationException("Wrapping AV exception", ex); 
     } 
    } 

我的問題是,怎麼了CLR知道治療包皮異常(InvalidOperationException異常在上面的示例)就像是一個CSE?

同樣,爲什麼如果你只是從託管代碼拋出一個新的AccessViolationException它而不是行爲像一個CSE? (...我承擔同樣的機制在起作用在這兩種情況下)

UPDATE: 繼漢斯的答案,這裏是表示AV異常的截圖被拋出一把抓住:screenshot

回答

1
catch (AccessViolationException ex) 

你犯了一個簡單的錯誤,否則也許說明了捕捉CSE的巨大危險。問題是你也必須知道要捕捉哪個CSE。有不止一個。

是的,這個事故作爲操作系統中的AVE啓動了。但是並沒有保持這種狀態,CLR對AVE的一個特殊規則是由較低的64KB內存訪問觸發的。它變成了一個NullReferenceException。你沒有抓到。修復:

catch (NullReferenceException ex) 

現在它工作正常。

+0

感謝漢斯 - 有趣的信息......但我沒有在我的機器上得到相同的行爲(例如,它肯定是調用Marshal.StructureToPtr()時被拋出的AVE)。 在原始示例中,我感興趣的是爲什麼它沒有在RunTest()中捕獲InvalidOperationException。 CLR不會將它呈現給catch塊,因爲它認爲它是一個CSE。如果將HPCSE屬性添加到R​​unTest,則會按設計吞下InvalidOperationException。 – 2015-01-16 09:25:30

+0

不,它絕對是一個被拋出的NullReferenceException。只需將其更改爲'var ptr = new IntPtr(65536);'以獲得AccessViolationException。 – 2015-01-16 09:39:22

+0

不在我的機器上:0)...我附上了一個截圖來演示。無論如何,ProvokeAccessViolation()中的catch可能只是catch(Exception ex)。我的問題是真的爲什麼然後不能捕捉RunTest()中的InvalidOperationException? – 2015-01-16 10:42:11