StackOverflow hatalarını ayıklama
Yürütme yığını çok fazla iç içe yöntem çağrısı içerdiğinden aşıldığında bir StackOverflowException hatası atılır. Yöntemlerin özyinelemeli olarakbirbirini çağırması nedeniyle bu durum çok sık oluşur.
Örneğin, aşağıdaki gibi bir uygulamanız olduğunu varsayalım:
using System;
namespace temp
{
class Program
{
static void Main(string[] args)
{
Main(args); // Oops, this recursion won't stop.
}
}
}
Main
yöntemi, yığın alanı kalmayıncaya kadar sürekli olarak kendisini çağırır. Yığın alanı kalmadığında yürütme devam edemez ve bu nedenle bir StackOverflowExceptionhatası oluşturulur.
> 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>
Bunun gibi bir çıkışla programdan çıkış gördüğünüzde, yinelenen yöntemlerin kaynak kodunu bulabilir ve çok sayıda çağrıya neden olan mantığı araştırabilirsiniz.
Hata ayıklayıcısını kullanma
Bu çağrı yığınını genellikle yukarıdaki konsolda görmek sorunlu kodu tanımlamak için yeterlidir. Sorun hala net değilse, hata ayıklamaya devam edebilirsiniz.
Bu örnek StackOverflowException gerçekleştiğinde bir çekirdek dökümü oluşturur, ardından dökümü lldb (yaygın bir Linux komut satırı hata ayıklayıcısı) içine yükler ve hata ayıklar.
Çökme sırasında döküm toplamak üzere yapılandırılmış uygulamayı çalıştırın.
> 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
Not
.NET 6, .NET çalışma zamanı davranışını yapılandıran ortam değişkenleri için
COMPlus_
yerine ön ekDOTNET_
standartlaştırır. Ancak,COMPlus_
ön eki çalışmaya devam eder. .NET çalışma zamanının önceki bir sürümünü kullanıyorsanız, ortam değişkenleri içinCOMPlus_
ön ekini kullanmaya devam etmelisiniz.dotnet-soskullanarak SOS uzantısını yükleyin.
dotnet-sos install
lldb'de dökümü açın ve yığını görüntülemek için
bt
(backtrace) komutunu kullanın.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 ...
Üst çerçeve
0x00007f59b40900cc
birkaç kez tekrarlanır.0x00007f59b40900cc
adresinde hangi yönetilen yöntemin bulunduğunu bulmak için SOSip2md
komutunu kullanın.(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
Belirtilen yöntem olan temp.Program.Main(System.String[]) ve kaynak "/temp/Program.cs @ 9" üzerindeki kodun yanlış ne yaptığını anlamaya çalışmak için bakın. Ek bilgi gerekiyorsa, işlemi incelemek için daha fazla hata ayıklayıcı veya SOS komutlarını kullanabilirsiniz.