Bagikan melalui


Men-debug kesalahan StackOverflow

StackOverflowException dilemparkan ketika tumpukan eksekusi meluap karena berisi terlalu banyak panggilan metode berlapis. Sangat sering ini terjadi karena metode saling memanggil secara rekursif.

Misalnya, Anda memiliki aplikasi sebagai berikut:

using System;

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

Metode Main akan terus memanggil dirinya sendiri sampai tidak ada lagi ruang tumpukan. Setelah tidak ada lagi ruang tumpukan, eksekusi tidak dapat dilanjutkan dan sehingga akan melemparkan 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>

Ketika Anda melihat program keluar dengan output seperti ini, Anda dapat menemukan kode sumber untuk metode berulang dan menyelidiki logika yang menyebabkan sejumlah besar panggilan.

Menggunakan debugger

Sering kali hanya melihat callstack ini pada konsol di atas sudah cukup untuk mengidentifikasi kode yang bermasalah. Namun jika masalahnya masih belum jelas, Anda dapat men-debug lebih lanjut.

Contoh ini membuat cadangan inti ketika StackOverflowException terjadi, lalu memuat cadangan ke lldb (debugger baris perintah Linux umum) dan men-debugnya.

  1. Jalankan aplikasi dengan dikonfigurasi untuk mengumpulkan dump saat terjadi crash.

    > 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
    

    Nota

    .NET 6 menstandarkan pada awalan DOTNET_ alih-alih COMPlus_ untuk variabel lingkungan yang mengonfigurasi perilaku run-time .NET. Namun, awalan COMPlus_ akan terus berfungsi. Jika Anda menggunakan versi runtime .NET sebelumnya, Anda masih harus menggunakan awalan COMPlus_ untuk variabel lingkungan.

  2. Instal ekstensi SOS menggunakan dotnet-sos.

    dotnet-sos install
    
  3. Buka cadangan di lldb dan gunakan perintah bt (backtrace) untuk menampilkan tumpukan.

    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. Bingkai atas 0x00007f59b40900cc diulang beberapa kali. Gunakan perintah ip2md SOSuntuk mengetahui metode terkelola apa yang terletak di alamat 0x00007f59b40900cc.

    (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. Lihat metode temp yang ditunjukkan, Program.Main(System.String[]) dan sumber "/temp/Program.cs @ 9" untuk melihat apakah Anda dapat menemukan kesalahan pada kode tersebut. Jika informasi tambahan diperlukan, Anda dapat menggunakan perintah debugger lebih lanjut atau SOS untuk memeriksa proses.