C# attraper une exception de dépassement de pile

j'ai reçu un appel récursif à une méthode qui lance une exception de débordement de pile. Le premier appel est entouré par un bloc try catch mais l'exception n'est pas pris.

Faire l'exception de dépassement de pile se comporter d'une manière spéciale ? Puis-je attraper/manipuler correctement l'exception ?

NB: le cas échéant:

  • l'exception n'est pas jetée dans le fil principal

  • l'objet où le code lance l'exception est chargé manuellement par assemblage.LoadFrom(...).CreateInstance(...)

98
demandé sur Ether 2009-10-21 11:15:40

9 réponses

à partir de la version 2.0, Une Exception relative au débordement des piles ne peut être invoquée que dans les circonstances suivantes.

  1. le CLR est exécuté dans un environnement hébergé où l'hôte permet spécifiquement de gérer les exceptions StackOverflow
  2. l'exception relative au débordement des piles est rejetée par code d'utilisateur et n'est pas attribuable à une situation réelle de débordement des piles ( référence )
91
répondu JaredPar 2009-10-21 07:20:08

la bonne façon est de fixer le débordement, mais....

vous pouvez vous donner une plus grande pile: -

using System.Threading;
Thread T = new Thread(threadDelegate, stackSizeInBytes);
T.Start();

vous pouvez utiliser le système.Diagnostic.StackTrace propriété FrameCount pour compter les cadres que vous avez utilisés et jeter votre propre exception quand une limite de cadre est atteinte.

ou, vous pouvez calculer la taille de la pile restante et jeter votre propre exception quand elle tombe en dessous d'un seuil: -

class Program
{
    static int n;
    static int topOfStack;
    const int stackSize = 1000000; // Default?

    // The func is 76 bytes, but we need space to unwind the exception.
    const int spaceRequired = 18*1024; 

    unsafe static void Main(string[] args)
    {
        int var;
        topOfStack = (int)&var;

        n=0;
        recurse();
    }

    unsafe static void recurse()
    {
        int remaining;
        remaining = stackSize - (topOfStack - (int)&remaining);
        if (remaining < spaceRequired)
            throw new Exception("Cheese");
        n++;
        recurse();
    }
}

attrape le fromage. ;)

42
répondu 2009-10-21 11:33:21

From the MSDN page on Stacoverflowexception s:

dans les versions précédentes du .NET Cadre, votre demande pourrait attraper un objet StackOverflowException (par exemple, pour récupérer à partir de la surabondance de la récursivité). Cependant, que la pratique est actuellement déconseillée parce que le code additionnel significatif est nécessaire pour attraper une pile de manière fiable exception de débordement et continuer l'exécution du programme.

à partir du. Net Framework la version 2.0, une StackOverflowException l'objet ne peut pas être attrapé par une tentative de capture le bloc et le processus correspondant est résilié par défaut. Conséquent, il est conseillé aux utilisateurs d'écrire leur code pour détecter et prévenir une pile débordement. Par exemple, si votre l'application dépend de la récursivité, utiliser un compteur ou une condition d'État pour terminez la boucle récursive. Note qu'une application qui héberge le common language runtime (CLR) can spécifiez que le CLR décharge domaine d'application où la pile l'exception de débordement se produit et processus correspondant continuer. Pour plus d'informations, voir Iclrpolicymanager Interface et Hébergement de la langue commune Runtime.

35
répondu Damien_The_Unbeliever 2009-10-21 07:19:08

Comme plusieurs utilisateurs l'ont déjà dit, vous ne pouvez pas intercepter l'exception. Cependant, si vous avez du mal à trouver où cela se passe, vous pouvez configurer visual studio pour qu'il casse quand il est lancé.

pour cela, vous devez ouvrir les réglages D'Exception du menu 'Debug'. Dans les versions plus anciennes de Visual Studio, C'est à' Debug ' - 'Exceptions'; dans les versions plus récentes, c'est à' Debug ' - 'Windows' - 'Exception Settings'.

une fois que vous avez le paramètres ouvert, développez 'Common Language Runtime Exceptions", développez Système, faites défiler vers le bas et cochez la case 'Système.StackOverflowException". Ensuite, vous pouvez regarder la pile d'appel et de rechercher le motif de répétition des appels. Cela devrait vous donner une idée de l'endroit où chercher pour réparer le code qui cause le débordement de la pile.

20
répondu Simon 2017-08-24 09:20:22

comme mentionné ci-dessus à plusieurs reprises, il n'est pas possible d'attraper un StackOverflowException qui a été soulevé par le système en raison de l'état de processus corrompu. Mais il y a une façon de noter l'exception comme un événement:

http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx

à partir de la version .net Framework 4, cet événement n'est pas soulevé pour les exceptions qui corrompent l'état du processus, comme les dépassements de pile ou les violations d'accès, à moins que le gestionnaire d'événements ne soit critique pour la sécurité et ne possède l'attribut HandleProcessCorruptedStateExceptionsattribute.

néanmoins votre application se terminera après avoir quitté la fonction event-function (un travail très sale autour, était de redémarrer l'application dans cet événement haha, ne l'ont pas fait et ne le feront jamais). Mais il est assez bon pour l'enregistrement!

dans les versions .net Framework 1.0 et 1.1, une exception non gérée se produit dans un thread autre que le thread principal de l'application est capturé par le moteur d'exécution et n'est donc pas la cause de la demande de résiliation. Il est donc possible de soulever l'exception sans que la demande ne prenne fin. À partir de la version 2.0 de .net Framework, ce backstop pour les exceptions non manipulées dans les threads enfants a été supprimé, car l'effet cumulatif de telles défaillances silencieuses incluait une dégradation de la performance, des données corrompues, et des serrures, qui étaient toutes difficiles à déboguer. Pour plus d'informations, y compris une liste des cas dans lesquels l'exécution ne se termine pas, consultez Exceptions dans les Threads gérés.

11
répondu FooBarTheLittle 2011-07-28 09:33:27

Oui de CLR 2.0 le débordement de la cheminée est considéré comme une situation non récupérable. Donc le runtime arrête toujours le processus.

pour plus de détails, veuillez consulter la documentation http://msdn.microsoft.com/en-us/library/system.stackoverflowexception.aspx

6
répondu Brian Rasmussen 2009-10-21 07:18:50

vous ne pouvez pas. Le CLR ne te laissera pas faire. Un débordement de pile est une erreur fatale et ne peut être récupéré.

5
répondu Matthew Scharley 2009-10-21 07:19:35

Vous ne pouvez pas comme la plupart des postes sont en expliquant, permettez-moi d'ajouter un autre domaine:

sur de nombreux sites Web, vous trouverez des gens disant que la façon d'éviter cela est d'utiliser un autre AppDomain donc si cela se produit, le domaine sera déchargé. C'est absolument faux (à moins que vous hébergiez votre CLR) car le comportement par défaut du CLR soulèvera un événement KillProcess, faisant tomber votre AppDomain par défaut.

5
répondu No hay Problema 2010-02-11 08:39:26

c'est impossible, et pour une bonne raison (pour un, Pensez à toutes ces captures(Exception) autour de).

si vous voulez continuer l'exécution après le débordement de la pile, Lancez du code dangereux dans un autre AppDomain. Les politiques CLR peuvent être paramétrées pour résilier le nom de domaine AppDomain courant sur overflow sans affecter le domaine original.

3
répondu ima 2009-10-21 08:17:31