6
votes

Comment éviter un débordement d'une pile?

Je compile mon code à l'aide de CsharpCodeProvider et crée de manière dynamique une instance de certaines catégories d'assemblage de résultat. Que j'appelle une méthode. Si la méthode a une récursion, je reçois StackoverflowException et mon application se termine.

Comment puis-je éviter cela? xxx

lié:

Qu'est-ce qu'un débordement de pile?


11 commentaires

Ne créez pas des boucles avec une récursion infinie.


Je ne pense pas que quiconque puisse éviter Stackoverflow


Pourriez-vous poster un exemple de code? Spécifiquement le bit qui a la récursion.


J'ai seulement cliqué sur cette question parce que je pensais que c'était un troll


N'écrivez aucun code.


C'est une dupe de dizaines de q déjà ici, telle que Stackoverflow .Com / Questions / 1110138 / What-Is-A-Stack-Overflow


Arrêtez de payer vos factures Internet ...


Je pensais aussi que c'était une post «méta» - demandant, sur «Stackoverflow», comment éviter «Stackoverflow». Montrez simplement à quel point ce site est devenu omniprésent, dans mon esprit, avec la phrase. Les écrivains dictionnaires peuvent devoir mettre à jour leurs définitions ;-)


Vous appelez Run (), qui appelle activé (), qui appelle ensuite exécutions () puis exécutez () les appels exécutés () à nouveau. Après tout cela, Run () est ensuite appelé plusieurs centaines de fois plus aboutissant .. débordant de la pile!


Peut-être avez-vous besoin de nous dire ce que vous essayez réellement de faire ...


* punk non destiné *


7 Réponses :


10
votes

Stackoverflow indique que votre récursion va trop profonde et que la pile est à court de mémoire. Par exemple:

namespace TestStackOverflow
{
    class Program
    {
        class StackOver : MarshalByRefObject
        {
            public bool Run()
            {
                return true; // Keep the application running. (Return false to quit)
            }
        }

        static void Main(string[] args)
        {
            // Other code...

            while (stack.Run());
        }

    }
}


0 commentaires

1
votes

Si la récursivité provoque un débordement de pile, le problème n'est pas lié à la compilation de la classe - une fonction récursive nécessite une condition de terminaison, car C # n'évoie pas (généralement) Optimiser les appels queunes .


0 commentaires

0
votes

Je n'ai pas de bon fond de CsharpCodeProvider, mais je sais que l'algorithme de la mise en œuvre de récursivité pourrait être mis en œuvre avec une boucle


0 commentaires

1
votes

Le seul moyen d'éviter les débordements de pile avec des fonctions récursives consiste à avoir une condition de sortie claire qui sera éventuellement satisfaite, quelle que soit l'entrée. Soit vous définissez une profondeur maximale et arrêtez de faire des appels récursifs une fois que vous l'avez atteint, ou assurez-vous que les données que vous examinez sont finies (et dans des limites raisonnables) ou une combinaison des deux.


0 commentaires

0
votes

OK. Peu importe l'utilisation de CsharpcodeProvider ou non. Je charge l'assemblage en utilisant la réflexion dans un autre domaine. Je pense que les domaines ont été créés pour une raison de sécurité. Comment puis-je protéger l'application de terminer ??? xxx


4 commentaires

Exécuter est à court terme. C'est la récursion infinie.


Ouais. Je vois ça. Les domaines dans le cadre .NET ont été désignés pour des raisons de sécurité. Si je comprends bien, je peux ne pas charger mon assemblage que de créer une instance de la méthode de classe et d'appel. Je pensais que je peux définir des autorisations pour le code dans un autre domaine.


Xeon - tu traînes? Est-ce que cela appartient à DailyWTF?


Non je ne suis pas traînée. Je sais que Stackoverflow ne peut pas être attrapé mais je pensais qu'appressains pourrait aider .....



8
votes

exécution est à court terme. C'est la récursion infinie. xxx


0 commentaires

0
votes

Chaque fois que vous appelez une méthode FOO à partir de la barre de méthode, la barre est ajoutée à la pile d'appels. La pile d'appels est utilisée pour garder une trace d'où le code était avant que la méthode a été appelée afin qu'il puisse y retourner lorsque FOO est terminé.

La fonction récursive suivante xxx

Après plusieurs récursions de l'appel factorial (5), la pile d'appels ressemblerait à ceci: xxx

à ce point n est 1, et la fonction cesse d'appeler l'appel récursif et Au lieu de cela, renvoie 1. Le programme commence ensuite à sauvegarder la pile d'appels et le tout retourne 120.

sans la pile d'appel Le programme ne saurait pas où revenir à l'exécution d'une méthode .

Supposons maintenant que le boîtier de base n'était pas là, et cela ressemblait à ceci: xxx

après plusieurs récursions de la factorielle d'appel (5 ) la pile d'appels ressemblerait à ceci: xxx

car il n'y a pas de point auquel le code s'arrête en s'appelant, il continuera à toujours, et la pile d'appels se développera et se développera et grandir prendre de plus en plus de mémoire jusqu'à ce qu'elle dépasse la mémoire A été alloué et l'exception Stackoverflow est lancée.

Il y a 2 façons de l'arrêter de se produire, le mieux dépend de la situation.

1 fournit un cas de base. Assurez-vous qu'il y a une condition qui est finalement atteinte qui arrête la fonction de se rappeler. Dans le cas factorial, il est que n == 1, mais il pourrait s'agir d'une certaine période écoulée, qu'elle ait recouvré un certain nombre de fois, que certains résultat de certains calculs se situent dans certaines limites. Tant que cela arrête de cruuser avant que la pile ne soit trop grande.

2 Retirez la récursion et réécris-le sans. Tout algorithme récursif peut être réécrit comme un algorithme non récursif. Ce n'est peut-être pas aussi propre et élégant, mais cela peut être fait. Dans l'argument factorial, cela peut être quelque chose comme: xxx

si l'objectif est d'exécuter continuellement la même fonction encore et encore, vous pouvez ré-écriture de la récursive xxx

comme xxx


0 commentaires