Déboguer des erreurs StackOverflow
Une StackOverflowException est levée quand la capacité de la pile d’exécution est dépassée en raison d’un trop grand nombre d’appels à la méthode imbriquée.
Par exemple, supposons que vous ayez une application comme suit :
using System;
namespace temp
{
class Program
{
static void Main(string[] args)
{
Main(args); // Oops, this recursion won't stop.
}
}
}
La méthode Main
s’appelle en permanence jusqu’à ce qu’il n’y ait plus d’espace de pile. Une fois qu’il n’y a plus d’espace de pile, l’exécution ne peut pas continuer et lève donc une StackOverflowException.
> dotnet run
Stack overflow.
Notes
Sur .NET 5 et les versions ultérieures, la pile des appels est sortie dans la console.
Notes
Cet article explique comment déboguer un dépassement de capacité de pile avec lldb. Si vous utilisez le système d’exploitation Windows, nous vous suggérons de déboguer l’application avec Visual Studio ou Visual Studio Code.
Exemple
Exécuter l’application avec celle-ci configurée pour collecter un vidage sur incident
> 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
Notes
.NET 6 se normalise sur le préfixe
DOTNET_
au lieu deCOMPlus_
pour les variables d’environnement qui configurent le comportement au moment de l’exécution de .NET. Toutefois, le préfixeCOMPlus_
continuera à fonctionner. Si vous utilisez une version précédente du runtime .NET, vous devez tout de même utiliser le préfixeCOMPlus_
.Installer l’extension SOS à l’aide de dotnet-sos
dotnet-sos install
Déboguer le vidage dans lldb pour voir la pile défaillante
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 ...
Le cadre supérieur
0x00007f59b40900cc
est répété plusieurs fois. Utilisez la commande SOSip2md
pour déterminer quelle méthode se trouve à l’adresse0x00007f59b40900cc
(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
Examinez la méthode indiqué temp.Program.Main(System.String[]) et la source « /temp/Program.cs @ 9 » pour voir si vous pouvez déterminer l’origine du problème. Si ce n’était toujours pas clair, vous pouvez ajouter la journalisation dans cette zone du code.