共用方式為


偵錯 StackOverflow 錯誤

當執行堆疊溢位時,會拋出 StackOverflowException,因為它包含過多的巢狀方法呼叫。 這種情況經常發生,因為方法會以遞歸方式 呼叫彼此

例如,假設您有應用程式,如下所示:

using System;

namespace temp
{
    class Program
    {
        static void Main(string[] args)
        {
            Main(args); // Oops, this recursion won't stop.
        }
    }
}

Main 方法會持續呼叫自己,直到沒有其他堆棧空間為止。 一旦不再有堆疊空間,執行就無法繼續,因此會擲回 StackOverflowException

> dotnet run
Stack overflow.
   at temp.Program.Main(System.String[])
   at temp.Program.Main(System.String[])
   at temp.Program.Main(System.String[])
   at temp.Program.Main(System.String[])
   at temp.Program.Main(System.String[])
   at temp.Program.Main(System.String[])
   <this output repeats many more times>

當您看到程式以類似輸出結束時,您可以找到重複方法的原始程式碼,並調查導致大量呼叫的邏輯。

使用調試程式

通常只要在上述控制臺上看到這個呼叫堆疊就足以識別有問題的程序代碼。 不過,如果問題仍然不清楚,您可以進一步偵錯。

此範例會在發生 StackOverflowException 時建立核心傾印,然後將傾印載入 lldb (常見的 Linux 命令行調試程式)並對其進行偵錯。

  1. 執行設定為在當機時收集傾印的應用程式。

    > export DOTNET_DbgEnableMiniDump=1
    > dotnet run
    Stack overflow.
    Writing minidump with heap to file /tmp/coredump.6412
    Written 58191872 bytes (14207 pages) to core file
    

    注意

    .NET 6 將標準化前綴為 DOTNET_,而不是 COMPlus_,用於設定 .NET 執行時間行為的環境變數。 不過,COMPlus_ 前綴會繼續運作。 如果您使用舊版的 .NET 運行時間,您仍應該使用環境變數的 COMPlus_ 前置詞。

  2. 使用 dotnet-sos 安裝 SOS 擴充功能。

    dotnet-sos install
    
  3. 在 lldb 中開啟傾印,並使用 bt (backtrace) 命令來顯示堆疊。

    lldb --core /temp/coredump.6412
    (lldb) bt
    ...
        frame #261930: 0x00007f59b40900cc
        frame #261931: 0x00007f59b40900cc
        frame #261932: 0x00007f59b40900cc
        frame #261933: 0x00007f59b40900cc
        frame #261934: 0x00007f59b40900cc
        frame #261935: 0x00007f5a2d4a080f libcoreclr.so`CallDescrWorkerInternal at unixasmmacrosamd64.inc:867
        frame #261936: 0x00007f5a2d3cc4c3 libcoreclr.so`MethodDescCallSite::CallTargetWorker(unsigned long const*, unsigned long*, int) at callhelpers.cpp:70
        frame #261937: 0x00007f5a2d3cc468 libcoreclr.so`MethodDescCallSite::CallTargetWorker(this=<unavailable>, pArguments=0x00007ffe8222e7b0, pReturnValue=0x0000000000000000, cbReturnValue=0) at callhelpers.cpp:604
        frame #261938: 0x00007f5a2d4b6182 libcoreclr.so`RunMain(MethodDesc*, short, int*, PtrArray**) [inlined] MethodDescCallSite::Call(this=<unavailable>, pArguments=<unavailable>) at callhelpers.h:468
    ...
    
  4. 頂端框架 0x00007f59b40900cc 會重複數次。 使用 SOSip2md 命令,找出位於 0x00007f59b40900cc 位址的 Managed 方法。

    (lldb) ip2md 0x00007f59b40900cc
    MethodDesc:   00007f59b413ffa8
    Method Name:          temp.Program.Main(System.String[])
    Class:                00007f59b4181d40
    MethodTable:          00007f59b4190020
    mdToken:              0000000006000001
    Module:               00007f59b413dbf8
    IsJitted:             yes
    Current CodeAddr:     00007f59b40900a0
    Version History:
      ILCodeVersion:      0000000000000000
      ReJIT ID:           0
      IL Addr:            0000000000000000
         CodeAddr:           00007f59b40900a0  (MinOptJitted)
         NativeCodeVersion:  0000000000000000
    Source file:  /temp/Program.cs @ 9
    
  5. 請查看所指定的方法 temp.Program.Main(System.String[]) 和其來源 "/temp/Program.cs @ 9",以找出程式碼的問題所在。 如果需要其他資訊,您可以使用進一步調試程式或 SOS 命令來檢查進程。