2009-06-05 8 views
2

Récemment, j'ai créé un programme en c, qui avait pour seul but de déborder la pile, en utilisant une méthode récursive. Apparemment, il n'y a pas de manière portable (comme un bloc try/catch, au moins en c), pour éviter que l'appel suivant à une fonction provoque un débordement de pile. Ma question est, à votre avis, les langages de haut niveau devraient offrir des alternatives sur le redimensionnement de la pile, peut-être un drapeau sur le compilateur, ou ces applications doivent être construites avec des langages de bas niveau.qui est responsable de la détermination de la taille de la pile

+0

Ceci devrait être re-étiqueté pour enlever la balise [stackoverflow]. – NascarEd

Répondre

1

La taille de la pile est normalement définie par les outils de construction que vous utilisez pour créer votre application, tels que le compilateur et l'éditeur de liens. Les moyens de le faire sont toujours spécifiques à la plate-forme et ne peuvent donc pas être réalisés par des langages de haut niveau normalisés ou des langages de bas niveau standardisés, d'ailleurs.

+1

En outre, pour un langage compilé, différentes plates-formes requièrent différentes quantités de pile pour faire la même chose. Parfois massivement différent. Donc, un programmeur ne peut pas savoir que (disons) 10k de pile est suffisant sur n'importe quelle plate-forme. Le compilateur ne peut pas non plus fonctionner, car le calcul de la profondeur de récursion est un problème. Donc même sur les langages/frameworks où vous pouvez spécifier la taille de la pile d'une manière standard (et j'en ai vu), cette fonctionnalité n'est pas aussi utile que vous pourriez l'espérer. –

2

Habituellement, je pense que ce n'est probablement pas une bonne idée de flirter avec les limites de l'ordinateur ou du système d'exploitation. Si vous vous trouvez débordant la pile, manquant de mémoire, manquant de poignées de fichier ouvertes et ce genre de chose, il est sage de repenser votre programme, plutôt que de se demander comment les limitations peuvent être évitées.

2

Généralement, c'est le travail du chargeur (ce qui charge vos fichiers EXE, corrige les références aux bibliothèques partagées, déplace le code, etc.) pour configurer les zones de mémoire, mais généralement en réponse aux champs de l'en-tête exécutable qui ont été mis là par l'éditeur de liens.

Mais ce genre de chose n'est couvert par aucune norme, c'est une chose au niveau du système d'exploitation.

1

Apparemment, il n'y a pas de manière portable (comme un bloc try/catch, au moins en c), pour éviter que l'appel suivant à une fonction provoque un débordement de pile. Cela permet de prendre en charge les plates-formes qui ne peuvent pas étendre la pile dynamiquement, et ne vérifie pas non plus lors de l'exécution à chaque appel que la pile est toujours dans les limites. Tout type de vérification (à moins d'être fait par le matériel) ralentirait la grande majorité du code qui ne se déplace jamais vers la fin de la pile, donc pas vraiment dans l'esprit de C ou C++.

Récursif trop profond est une exception matérielle (ou corruption de mémoire). C et C++ n'essaient pas de spécifier ce qui se passe sur une exception matérielle: ils sont en dehors de la portée des langages et du comportement indéfini, donc il n'y a pas de moyen portable de récupérer. En revanche, Java lève StackOverflowError lorsque vous recurse trop profondément. Bien que non recommandé, il est possible d'attraper cela.

Je n'ai pas vu une langue avec une primitive isThereEnoughStackFor, qui vous permettra d'écrire:

if (isThereEnoughStackFor(foo)) { 
    foo(12); 
} else { 
    printf("error - no stack\n"); // I hope there's enough stack for printf 
} 

Pour un tel système fonctionne, vous devez savoir combien pile foo nécessite. Cela dépend de foo, mais aussi potentiellement de tout ce que foo appelle, et donc de ses paramètres. Donc foo et toutes ses dépendances doivent soit indiquer combien de pile ils requièrent (dans ce cas, comment savez-vous qu'il y a assez de pile pour le calculer?), Soit faire des contrôles similaires avant d'appeler quoi que ce soit (auquel cas vous d avoir un menu limité de fonctions que vous êtes "autorisé" à appeler, comme dans les gestionnaires de signaux). Une fois que vous avez un polymorphisme d'exécution (en C, pensez si foo est un pointeur de fonction plutôt qu'un nom de fonction), vérifier la pile par d'autres moyens que les tests intégrés à chaque appel s'avère impossible ou non valable l'effort.

Questions connexes