2017-10-18 56 views
1

我明白爲什麼代碼不能工作。我不明白是什麼技術原因造成的,所以我們沒有得到更明確的錯誤信息。爲什麼IIS在循環構造函數中給出了廣泛的「502.3 - Bad Gateway」錯誤

在開發netcore2應用程序時,我最終使用構造函數進行循環引用。我的意思是類A的構造函數實例化了另一個類型爲B的對象,它本身會實例化一個類型爲A的對象等等。

這是一個簡單的代碼片段,用於重現圓形實例化,該實例在online compiler上引發StackOverflowException我做了這個例子。

public class A 
{ 
    public A() 
    { 
     var b = new B(); 
    } 
} 

public class B 
{ 
    public B() 
    { 
     var b = new B(); 
    } 
} 

public class Program 
{ 
    public static void Main(string[] args) 
    { 
     var a = new A(); 
    } 
} 

令人驚訝,而不是一個計算器例外它是一個502.3 - Bad Gateway錯誤IIS給我的應用程序崩潰,這並沒有給有關基本問題的大量信息之前。我期望這樣的循環調用可以輕鬆地檢測到它不僅被編譯器捕獲,而且甚至可以被VisualStudio 2017或Resharper最終指出,但沒有任何警告我。

this article以及this one似乎表明問題可能是暫停,但似乎不大可能,因爲應用程序在兩秒鐘內崩潰。

我簡直不明白爲什麼沒有CircularConstructionException - 這聽起來很容易實現,甚至更糟糕的是,爲什麼IIS沒有像聯機編譯器那樣拋出常規StackOverflowException

+1

502.3也不例外。實際的異常很可能是StackOverflowException。 502.3甚至可能不是來自IIS--它可能來自您和IIS之間的代理。 –

+1

我不知道它是否重要,但這是在本地,在調試模式。對於拋出的其他異常,我會得到一個包含詳細信息的異常頁面。爲什麼在這種情況下只能隱藏異常?我有點理解爲什麼應用程序崩潰(無法擺脫循環),但爲什麼是StackOverflow或任何異常實際上是由IIS在調試模式下隱藏的? – Wndrr

回答

3

我相信正確的答案是它是C#的設計決定。鑑於其他例外情況在您的案例的例外頁中被捕獲幷包裝,StackOverflowException會導致進程終止,這是報告502.3響應(報告連接失敗)的原因。


從MSDN頁面上StackOverflowException S:

在.NET框架 以前的版本,您的應用程序可以 趕上StackOverflowException對象 (例如,從 無限遞歸恢復)。然而, 做法是目前氣餒 因爲顯著的額外代碼可靠趕上一個堆棧溢出 異常並繼續 執行程序需要 。

與.NET Framework 2.0版本開始,StackOverflowException 對象不能由一個try-catch 塊捕獲和相應的過程是 默認終止。因此, 建議用戶編寫他們的代碼 來檢測並防止堆棧 溢出。例如,如果您的 應用程序依賴於遞歸,請使用 計數器或狀態條件來終止遞歸循環。注意 承載公共語言運行時(CLR)的應用程序可以指定CLR卸載發生堆棧 溢出異常的應用程序域,並讓相應的進程繼續。有關 的更多信息,請參閱 ICLRPolicyManager接口和 承載公共語言運行時。

+0

非常感謝您指向相應MSDN頁面的指針。所以它確實是這樣的。我將深入研究MSDN頁面提到的ICLRPolicyManager。 – Wndrr

0

該類調用itsef不定式時間和造成堆棧溢出

public class B 
{ 
    public B() 
    { 
     var b = new B(); 
    } 
} 
+0

你的陳述是真實的,但是這並不回答這個問題。無論如何感謝您的時間:-) – Wndrr

1

我只是不明白爲什麼沒有CircularConstructionException - 這聽起來很容易的實現

有在運行時關於實例化另一個對象的對象甚至是相同類型的對象都不是非法的。問題是你沒有正確控制堆棧,所以StackOverflowException實際上是合適的。在這種情況下,可以說這個問題可以被編譯器檢測到,但這仍然不是運行時異常。

甚至更​​糟糕的是,爲什麼不是IIS像聯機編譯器一樣拋出常規的StackOverflowException?

IIS可能不知道爲什麼它死了。它創建一個工作進程來運行你的應用程序;該進程因堆棧溢出而死亡。 IIS主機進程然後返回一個錯誤,指示工作進程失敗。也許「壞的網關」不是最清楚的,但IIS主機不知道堆棧溢出。它只知道它的工作進程沒有響應或死機。

+0

感謝您對IIS內部行爲的進一步解釋。我希望我能標出兩個答案是正確的。 – Wndrr

相關問題