Depurar erros do StackOverflow
Um StackOverflowException é emitido quando a pilha de execução excede porque contém demasiadas chamadas de método aninhadas.
Por exemplo, suponha que tem uma aplicação da seguinte forma:
using System;
namespace temp
{
class Program
{
static void Main(string[] args)
{
Main(args); // Oops, this recursion won't stop.
}
}
}
O Main
método chamar-se-á continuamente até que não haja mais espaço na pilha. Assim que não houver mais espaço na pilha, a execução não pode continuar e, por isso, irá lançar um StackOverflowException.
> dotnet run
Stack overflow.
Nota
No .NET 5 e posterior, a pilha de chamadas é saída para a consola.
Nota
Este artigo descreve como depurar uma pilha com lldb. Se estiver a executar no Windows, sugerimos que depure a aplicação com o Visual Studio ou o Visual Studio Code.
Exemplo
Executar a aplicação com a mesma configurada para recolher uma informação de falha de sistema
> 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
O .NET 6 uniformiza o prefixo
DOTNET_
em vez de para variáveis deCOMPlus_
ambiente que configuram o comportamento de tempo de execução do .NET. No entanto, oCOMPlus_
prefixo continuará a funcionar. Se estiver a utilizar uma versão anterior do runtime do .NET, deve continuar a utilizar oCOMPlus_
prefixo para variáveis de ambiente.Instalar a extensão SOS com dotnet-sos
dotnet-sos install
Depurar a captura no lldb para ver a pilha com falhas
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 moldura
0x00007f59b40900cc
superior é repetida várias vezes. Utilize o comando SOSip2md
para descobrir que método está localizado no0x00007f59b40900cc
endereço(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
Veja a temp do método indicado. Program.Main(System.String[]) e a origem "/temp/Program.cs @ 9" para ver se consegue descobrir o que fez de errado. Se ainda não estivesse claro, poderia adicionar o registo nessa área do código.