2009-10-08 5 views
0

J'ai l'exemple de code suivant pour illustrer mon point. Quand je charge ceci dans IE8 sur Vista j'obtiens l'erreur "Stack Overfow à la ligne: 16"Dépassement de pile après 15 récursions avec la fonction de classe Javascript

Si je recurse en utilisant une fonction de niveau supérieur (en dehors de l'objet testClass) je peux recurse des millions de fois sans débordement de pile.

Pourquoi cela se produit-il? En fin de compte, j'ai juste implémenté une Fonction Que au lieu d'utiliser la récursivité, mais cela n'a tout simplement pas de sens pour moi, et j'aimerais en comprendre la cause.

- Code -

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"> 
<html> 
    <head> 
     <title>Recusion Test</title> 
     <body> 
     </body> 

     <script type="text/javascript"> 

      function testClass() { 
       this.x = 15; 
       this.recurse = function() { 
        this.x--; 
        this.recurse(); 
       } 
      } 

      var wtf = new testClass(); 
       wtf.recurse(); 

      alert('done'); 
     </script> 
    </head> 
</html> 
+0

Ok, c'était une erreur de ma part, j'ai simplifié une classe complexe à des fins de démonstration et j'ai oublié de l'inclure. Voir ma réponse ci-dessous. Dans ma base de code actuelle, j'ai été capable de se reproduire 14 fois sans SO, mais à 15 ans il échouerait. –

Répondre

7

Il n'y a pas de condition de terminaison pour votre déclaration récursive donc il fonctionnera toujours.

Il semble que vous voulez ...


      function testClass() { 
       this.x = 15; 
       this.recurse = function() { 
        if (this.x--) 
         this.recurse(); 
       } 
      } 

      var wtf = new testClass(); 
       wtf.recurse(); 

      alert('done'); 
1

Ok, voici encore quelques informations sur la question que je faisais. Après être retourné et réparé ce que je pensais être le problème avec mon application, j'avais toujours le problème. La partie qui m'a fait poursuivre la question était que si je ne recourais que 14 fois, cela se terminerait avec succès. D'abord, j'exécutais le code original dans un HTA et non Internet Explorer. J'écris un éditeur de code basé sur VIM similaire à FCKEditor.

Deuxièmement, la structure de mon code est le suivant:

-HTA

--EditorClass

--- DivManagerClass

---- KeyBindingClass

En mon KeyBindingClass J'ai eu une base de code similaire à l'exemple fourni (sauf qu'il a une condition de fin)

Dans ma KeyBindingClass, j'ai une propriété de répéteur qui répéterait la dernière touche N fois si un modificateur numérique a été pressé. Pour ceux qui ne savent pas appuyer sur les touches '3' et 'x' en mode visuel dans vim va supprimer trois caractères.

Tout fonctionnait bien jusqu'à ce que j'utilisé un modificateur numérique supérieur à 14.

je continuais à essayer de reproduire ce problème avec un petit harnais de test et ne pouvait pas. J'ai été capable de recurse jusqu'à 3000 dans un harnais de test de base. J'ai donc commencé à recréer le scénario du mieux que je pouvais. J'ai d'abord déplacé l'appel à la méthode recurse dans une autre classe/méthode. Cela a limité ma pile d'appels à quelque chose autour de 1600 (presque la moitié de la pile a juste disparu.)

Puis j'ai ajouté jQuery au mélange et déplacé l'appel à la méthode ParentClass.recurse dans un événement keybinding dans le document. . Cela a réduit ma callstack à environ 1300.

Ensuite, j'ai déplacé mon code dans un HTA qui a réduit de moitié ma pile d'appels! Après avoir imité le mieux possible ma base de code, j'ai atteint une callstack d'environ 515.

Après quelques recherches, j'ai trouvé que l'IE utilisait l'espace mémoire disponible pour déterminer la taille de la pile.Je suppose que la HTA est un peu plus stricte à cet égard. Je n'ai pas compris quel autre facteur a limité mon application à un callstack si bas étant donné la structure des classes, mais c'est la structure du code qui pose problème.

Je peux mettre mon test de récursion de base dans une balise de script d'exécution de niveau supérieur et obtenir environ 1473 appels avant d'atteindre un dépassement de capacité de la pile. Je peux toujours utiliser une file d'attente de fonctions pour résoudre mon problème, mais je voulais juste que les autres sachent que A. Je ne publierais pas un problème si simple à Stack Overflow, et B. que votre limite de pile d'appel peut être énormément affectés par les structures de classe entourant les fonctions, même si elles ne sont pas des niveaux séparés de ce que vous considériez traditionnellement comme une pile de fonctions.

Questions connexes