StackOverflow 오류 디버그
StackOverflowException 너무 많은 중첩된 메서드 호출을 포함하기 때문에 실행 스택이 오버플로될 때 throw됩니다. 메서드가 재귀적으로 서로 호출하기 때문에 이 문제가 자주 발생합니다.
예를 들어 다음과 같이 앱이 있다고 가정합니다.
using System;
namespace temp
{
class Program
{
static void Main(string[] args)
{
Main(args); // Oops, this recursion won't stop.
}
}
}
Main
메서드는 스택 공간이 더 이상 없을 때까지 계속해서 자신을 호출합니다. 스택 공간이 더 이상 없으면 실행을 계속할 수 없으므로 StackOverflowExceptionthrow됩니다.
> 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 명령줄 디버거)에 덤프를 로드하고 디버그합니다.
크래시 시 덤프를 수집하도록 설정한 앱을 실행합니다.
> 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은 .NET 런타임 동작을 구성하는 환경 변수에 대한
COMPlus_
대신 접두사DOTNET_
표준화합니다. 그러나COMPlus_
접두사는 계속 작동합니다. 이전 버전의 .NET 런타임을 사용하는 경우에도 환경 변수에COMPlus_
접두사를 사용해야 합니다.dotnet-sos사용하여 SOS 확장을 설치합니다.
dotnet-sos install
lldb에서 덤프를 열고
bt
(백트레이스) 명령을 사용하여 스택을 표시합니다.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 ...
0x00007f59b40900cc
위쪽 프레임은 여러 번 반복됩니다. SOSip2md
명령을 사용하여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
지정된 메서드 temp.Program.Main(System.String[]) 및 소스 "/temp/Program.cs @ 9"를 확인하여 코드에 어떤 오류가 있는지 파악할 수 있는지 확인합니다. 추가 정보가 필요한 경우 추가 디버거 또는 SOS 명령을 사용하여 프로세스를 검사할 수 있습니다.
.NET