2013-04-09 109 views
4

我知道這非常含糊,但這是我可以收集的。我希望有人對這種情況如何發生有所瞭解。C#無法捕捉到StackOverflowException或看看它發生了什麼

我有我的Win 7 64位機器上運行64位程序,內置在Visual Studio 2012

它使用位於另一個項目(編譯爲DLL)的一類。該類有一個可能導致堆棧溢出的錯誤迭代器。調用錯誤迭代器的操作通過任務調用。

所以在我的程序,代碼如下所示:

new Task(()=>{ 
try 
{ 
    DoWork(); //<-- buggy iterator is called inside 
} 
catch (Exception ex) 
{ 
    //Exception reported to user 
} 
}).Start(); 

的代碼是在相同的數據,每次執行,並具有參與所以每次應該產生相同的輸出沒有隨機變量或GUID生成。

大多數情況下,它會崩潰StackOverflowException發生在未知模塊(即使我知道事實上它發生的確切位置)。如果發生這種情況,我無法查看溢出發生的代碼,try-catch塊什麼也不做!我無法繼續執行程序(如果我運行它而不進行調試,它顯示「程序必須關閉,讓我們在線檢查解決方案」系統窗口)。

現在,它有時會捕獲異常(顯示導致異常的代碼中的正確位置)。這是隨機的,但如果我更頻繁地中斷任務(如在工作期間隨機插入斷點),似乎會發生更多。

但是,我仍然無法繼續申請。即使異常發生在應該捕獲StackOverflowException的try-catch塊內(它應該被捕獲,因爲StackOverflowException包含在Exception中 - C#不會讓你捕獲它們並明確告訴你SOE已經包含在E中)。

我試圖製作一個小程序,在try-catch塊內部蓄意堆棧溢出,它也顯示「程序必須關閉讓我們在線檢查解決方案」系統窗口,而不是正確處理。下面的代碼:

private bool Overflow() 
    { 
     return Overflow(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     try { Overflow();} 
     catch (StackOverflowException ex) { } 
    } 

所以,我有幾個問題:

問題1:

是否有可能趕上StackOverflowExceptions永遠不會消失?我該怎麼做?

問題2:

當堆棧溢出您的DLL(在相同的解決方案等項目)內發生的,有什麼可以讓VS 2012調試器認爲它是「未知模塊」?

問題3:

爲什麼做一些奇怪的魔法舞蹈與部落樂器使得它做到這一點往往少嗎? (我的意思是隨機打破程序進行中)

總體而言,發生了什麼事?

在此先感謝

回答

1

你不允許搭上真正堆棧溢出異常,這就是爲什麼它不會工作。

另請參閱this討論。

我不能回答你的第二個問題,除了說「該程序真的搞砸了」。

對於第三個問題:因爲它在一個單獨的線程中運行,所以它運行的代碼量將根據您何時中斷程序而有所不同。我認爲只有通過一些繁瑣的逐行調試,或者大量的Debug.WriteLine()才能實現這一點。

+0

在這個討論中,他們說如果CLR在託管環境中運行,主機特別允許處理StackOverflow異常*,那麼可以捕獲它。我怎麼做才能讓這些例外得到處理? – Istrebitel 2013-04-09 08:45:47

+0

您如何託管CLR環境?凡人不能輕易...這是對於像SQL服務器和調試器的東西。有關更多詳細信息,請參見[此處](http://stackoverflow.com/questions/2348207/what-is-clr-hosting)。準備用C++編寫主機。 – 2013-04-09 11:06:50

0

1)從.NET Framework 2.0版開始,StackOverflowException對象不能被try-catch塊捕獲,並且相應的進程默認終止。因此,建議用戶編寫代碼來檢測和防止堆棧溢出。例如,如果您的應用程序依賴於遞歸,請使用計數器或狀態條件來終止遞歸循環。請注意,承載公共語言運行庫(CLR)的應用程序可以指定CLR卸載發生堆棧溢出異常的應用程序域,並讓相應的進程繼續。有關更多信息,請參閱ICLRPolicyManager接口和主機概述。 (http://msdn.microsoft.com/en-us/library/system.stackoverflowexception.aspx