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

  1. 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 de COMPlus_ pour les variables d’environnement qui configurent le comportement au moment de l’exécution de .NET. Toutefois, le préfixe COMPlus_ continuera à fonctionner. Si vous utilisez une version précédente du runtime .NET, vous devez tout de même utiliser le préfixe COMPlus_.

  2. Installer l’extension SOS à l’aide de dotnet-sos

    dotnet-sos install
    
  3. 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
    ...
    
  4. Le cadre supérieur 0x00007f59b40900cc est répété plusieurs fois. Utilisez la commande SOSip2md pour déterminer quelle méthode se trouve à l’adresse 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
    
  5. 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.

Voir aussi