2020年10月1日 星期四

Stack Overflow 造成的原因

Stack Overflow 造成的原因

在進行程式設計的時候,經常會聽到 記憶體不足 這樣的問題,其中,對於記憶體不足這樣的現象,會發生在兩種情況下,在這裡將會展示出如何過度使用 執行緒推疊 Stack Overflow。

當在設計類別中的方法時候,對於該方法所使用的參數或者區域變數,若這兩種物件的型別為 數值型別 Value Type,則該物件將會從堆疊結構中取得一個空間來作為儲存、存放的地方,然而,若是一個 參考型別 Reference Type ,則會從堆疊結構中取得一個該參考型別的位置儲存空間,並且要求 堆積 Heap 取得一塊空間,用來儲存該參考物件的相關執行個體內容。

在上面的說明中,可以看到對於 .NET 系統中,將會有兩種類型的記憶體儲存空間,一個是 Heap,這裡將會存放各種參考型別物件值,而且這裡可用的空間非常大,另外一種是 Stack,這裡的空間會使用當前執行緒所配置的空間來使用,而在 .NET 中,一個執行緒在建立的時候,預設將會擁有 1MB 的記憶體空間,任何在方法呼叫過程中,對於參數與區域變數,將會使用這裡的空間。

因此,底下的範例,將會設計一個方法 [NestRecursionMethod] ,這個方法將會自我遞迴呼叫,在這個方法內,將宣告五個 decimal 數值型別的區域變數,每個 decimal 物件,將會耗用 16 bytes的記憶體空間,所以,五個 decimal 物件,將會耗用 16*5 = 80 bytes 記憶體空間;當然在呼叫方法的過程中,還會有其他的資料會儲存在 Thread Stack 這個資料結構空間內。

在這個程式中,因為會反覆呼叫 [NestRecursionMethod] 方法,進而造成 Stack 記憶體空間不斷減少,一旦該 Stack 內沒有足夠的記憶體空間,將會造成 Stack 空間不足,也就是會拋出 Stack Overflow 的例外異常。

這裡是最後執行後的螢幕輸出結果

.
.
.
Level 3818
Level 3819
Level 3820
Level 3821
Level 3822
Level 3823
Level 3824
Level 3825
Level 3826
Stack overflow.

而在 Visual Studio 2019 內,將會看到這樣的例外異常提示畫面

這裡將會是該例外異常的詳細資訊

System.StackOverflowException
  HResult=0x800703E9
  Source=<無法評估例外狀況來源>
  StackTrace: 
<無法評估例外狀況堆疊追蹤>
class Program
{
    static void Main(string[] args)
    {
        int level = 1;
        Console.WriteLine("Hello World!");
        NestRecursionMethod(level);
    }
 
    private static void NestRecursionMethod(int level)
    {
        // 一個 decimal 使用 16 bytes 空間
        decimal decimal1=1;
        decimal decimal2= decimal1+1;
        decimal decimal3 = decimal2 + 1;
        decimal decimal4 = decimal3 + 1;
        decimal decimal5 = decimal4 + 1;
        Console.WriteLine($"Level {level}");
        NestRecursionMethod(++level);
    } 

} 




沒有留言:

張貼留言