2017-08-21 2 views
0

J'essaie d'écrire une bibliothèque qui peut analyser les fichiers d'utilisateurs finaux à utiliser pour ajouter du contenu simple généré par l'utilisateur dans un projet et je veux essayer de rendre la bibliothèque aussi flexible que possible. possible. J'utilise la récursion pour le processus de tokenisation des 'objets' qui passe par une chaîne de quatre fonctions, mais je suis en conflit avec la façon de gérer la situation potentielle d'un utilisateur final qui va heureusement à l'objet imbriqué. Je sais que je peux fixer une limite stricte sur combien de fois le programme peut se reproduire mais je voudrais le rendre aussi flexible que possible. Y a-t-il un moyen de calculer le nombre (maximum - 1) de fois que ce processus peut s'exécuter de sorte que je puisse anticiper une erreur de débordement de pile et renvoyer une erreur ou quelque chose à gérer?C++ Empêcher les empilements de dépassement

+5

Toute récursion peut être réécrite en tant qu'itération plus pile explicite. De cette façon, vous n'êtes pas limité par la taille de la pile des appels, mais seulement par la mémoire disponible sur le système. –

+2

La norme C++ ne spécifie pas les moyens permettant de déterminer l'espace de pile disponible requis pour un appel de fonction récursif, ni la quantité d'espace de pile disponible pour un processus. –

+0

@IgorTandetnik Cela semble intéressant et un bon moyen d'aller. Les fonctions de la chaîne préforment un certain nombre de vérifications et certaines de ces vérifications et renvoient des informations dans la chaîne. Seriez-vous capable de me diriger vers des tutoriels ou des articles qui parlent d'une éventuelle mise en œuvre? – MitchellCroft

Répondre

2

Est-il possible que je peux calculer la (maximum - 1) nombre de fois que ce processus [récursive] peut exécuter ...

Non, il est même pas garanti que chaque cadre de pile dans la chaîne d'appel est la même taille.

Transformer une implémentation récursive à un processus itératif est assez simple et très bien défini: vous venez

  1. remplacer la pile d'appel implicite (et le fonctionnement appel de fonction) avec un conteneur explicite de l'État, comme std::stack<State>
  2. au lieu d'un appel récursif, vous appuyez sur State de nouvel appel sur votre pile, et continuer la boucle
  3. au lieu d'être appelé, la boucle commence par sauter le State courant de la pile, et les processus, ce qui peut nécessiter de pousser un autre nouveau State là-bas si vous aurait déjà fait un appel récursif

Alternativement, vous pouvez simplement diviser votre analyseur en cours de descente récursive dans un tokenizer et analyseur LALR (ou similaire), qui sont à la fois itérative en premier lieu. Vous pouvez les générer avec Flex et Bison (Lex/Yacc), par exemple.

1

Sous Windows, vous pouvez utiliser le framework SEH pour intercepter l'exception de débordement de pile en utilisant __try/__ excepté et quitter votre programme.
Cependant, si votre application utilise C++, vous devrez compiler en utilisant l'option/EHa ou/EHsc. Cochez ce lien pour plus de détails sur l'utilisation de SEH avec C \ C++ et sur les spécificités d'utilisation des drapeaux/EHa et/EHsc.
https://docs.microsoft.com/en-us/cpp/cpp/structured-exception-handling-c-cpp

__try 
{ 
    //code which might generate stack overflow 
} 
__except(EXCEPTION_EXECUTE_HANDLER) 
{ 
    //handle stack overflow exception, throw error and exit program  
} 

Hope this helps!