StackOverflow-hibák hibakeresése
A StackOverflowException hibát dobják, amikor a végrehajtási verem túlcsordul, mert túl sok beágyazott metódushívást tartalmaz. Ez gyakran azért fordul elő, mert a metódusok rekurzívan hívják egymást .
Tegyük fel például, hogy az alábbi alkalmazással rendelkezik:
using System;
namespace temp
{
class Program
{
static void Main(string[] args)
{
Main(args); // Oops, this recursion won't stop.
}
}
}
A Main
metódus folyamatosan meghívja magát, amíg nincs több veremterület. Ha nincs több veremterület, a végrehajtás nem folytatható, ezért egy StackOverflowException-t dob.
> 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>
Ha a program ekkora kimenettel lép ki, megtalálhatja az ismétlődő metódus(ok) forráskódját, és megvizsgálhatja a nagy számú hívást kiváltó logikát.
A hibakereső használata
A fenti konzolon gyakran elég ezt a híváshívást látni a problémás kód azonosításához. Ha azonban a probléma továbbra sem egyértelmű, további hibakeresést végezhet.
Ez a példa létrehoz egy magmemóriaképet, amikor a StackOverflowException történik, majd betölti a memóriaképet az lldb-be (egy gyakori Linux parancssori hibakereső), és hibakeresést végez rajta.
Futtassa az alkalmazást úgy beállítva, hogy az összeomláskor memóriaképet gyűjtsö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
Jegyzet
A .NET 6 a .NET futásidejű viselkedést konfiguráló környezeti változók
COMPlus_
helyett aDOTNET_
előtagon szabványosít. ACOMPlus_
előtag azonban továbbra is működni fog. Ha a .NET-futtatókörnyezet egy korábbi verzióját használja, akkor is a környezeti változókCOMPlus_
előtagját kell használnia.Telepítse az SOS-bővítményt dotnet-soshasználatával.
dotnet-sos install
Nyissa meg a memóriaképet az lldb-ben, és használja a
bt
(backtrace) parancsot a verem megjelenítéséhez.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 ...
A felső keret
0x00007f59b40900cc
többször ismétlődik. Az SOSip2md
paranccsal állapítsa meg, hogy melyik felügyelt metódus található a0x00007f59b40900cc
címé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
Ellenőrizze a jelzett metódust temp.Program.Main(System.String[]) és a forrás "/temp/Program.cs @ 9" fájlban, hogy kiderítse, miért hibás a kód. Ha további információra van szükség, használhat további hibakereső eszközöket vagy SOS parancsokat a folyamat vizsgálatához.