2008-09-19 7 views
6

Vous pouvez penser que c'est une coïncidence que le sujet de ma question est similaire au nom du forum, mais je suis arrivé ici en tapant sur Google le terme "stack overflow". J'utilise le simulateur de réseau OPNET dans lequel je programme en utilisant C. Je pense que j'ai un problème avec les grandes tailles de tableau. Il semble que je frappe une sorte de limitation d'allocation de mémoire. Cela peut concerner OPNET, Windows, la mémoire de mon ordinateur portable ou le langage C le plus probable. Le problème est causé lorsque j'essaie d'utiliser des tableaux imbriqués avec un nombre total d'éléments arrivant à plusieurs milliers d'entiers. Je pense que je dépasse une limite globale d'allocation de mémoire et je me demande s'il y a un moyen d'augmenter ce plafond. Voici la description exacte du problème:Qu'est-ce qui provoque un débordement de pile?

J'ai essentiellement une table de routage. Appelons-le routing_tbl [n], ce qui signifie que je supporte 30 nœuds (routeurs). Maintenant, pour chaque noeud de cette table, je garde des informations. à propos de plusieurs (centaines) chemins disponibles, dans un tableau appelé chemins [p]. Encore une fois, pour chaque chemin de ce tableau, je garde la liste des nœuds qui lui appartiennent dans un tableau appelé hops [h]. Donc, j'utilise au moins nph valeurs entières de mémoire mais cette table contient aussi d'autres informations. Dans la même fonction, j'utilise également un autre tableau imbriqué qui consomme près de 40 000 entiers. Dès que je lance ma simulation, il cesse de se plaindre du débordement de la pile. Cela fonctionne quand je réduis la taille totale de la table de routage. D'après vous, qu'est-ce qui cause le problème et comment peut-il être résolu? Très apprécié Ali

+0

Pourriez-vous expliquer le problème de manière plus explicite que votre solution actuelle? Je pense que cela encouragerait plus de gens à lire et à répondre à votre question. –

Répondre

10

Cela peut être utile si vous postez du code. Modifiez la question pour inclure la fonction de problème et l'erreur.

En attendant, voici une réponse très générique:

Les deux principales causes d'un débordement de la pile sont 1) une fonction récursive, ou 2) l'attribution d'un grand nombre de variables locales.

Recursion

si votre fonction elle-même appelle, comme ceci:

int recurse(int number) { 

    return (recurse(number)); 
} 

Comme les variables locales et les arguments de la fonction sont stockés sur la pile, puis il en remplir la pile et causer une pile débordement.

grandes variables locales

Si vous essayez d'allouer un large éventail de variables locales, vous pouvez déborder la pile en une seule fois facile. Une fonction comme celui-ci peut provoquer le problème:

void hugeStack (void) { 

    unsigned long long reallyBig[100000000][1000000000]; 

    ... 
} 

Il y a toute une réponse détaillée à cette similar question.

+0

Techniquement, la fonction de récursion serait optimisée en une boucle infinie simple, mais ne soyons pas trop pessimistes avec l'exemple :) –

+0

Étant donné la description, cela ressemble au problème de données trop poussé sur la pile plutôt que de récursivité. Je parie que mettre des variables sur le tas (avec malloc) résoudra le problème. –

+0

Ouais, c'est ce qu'on m'a répondu au début, mais ensuite j'ai pensé qu'il pourrait traverser son réseau avec une certaine fonction. J'ai pensé que j'ajouterais juste une réponse de référence de base et n'importe qui d'autre qui erre de cette manière peut avoir une idée. Qui sait, ce noob pourrait ne jamais revenir :) –

1

Les dépassements de pile peuvent se produire en C lorsque le nombre d'appels récursifs incorporés est trop élevé. Peut-être que vous appelez une fonction de lui-même trop de fois?

Cette erreur peut également être due à l'allocation de trop de mémoire dans les déclarations statiques. Vous pouvez passer aux allocations dynamiques via malloc() pour résoudre ce type de problème.

Y at-il une raison pour laquelle vous ne pouvez pas utiliser le débogueur sur ce programme?

+0

Picky, je sais, mais les profondeurs ne sont pas "hautes" elles sont "profondes". Pardon. – Cyberherbalist

3

D'une manière ou d'une autre, vous utilisez beaucoup de pile.Les causes possibles sont que vous créez la table de routage sur la pile, que vous la transmettez sur la pile, ou que vous générez beaucoup d'appels (par exemple en traitant récursivement le tout).

Dans les deux premiers cas, vous devez le créer sur le tas et lui passer un pointeur. Dans le troisième cas, vous devrez réécrire votre algorithme sous une forme itérative.

+0

Comment pouvez-vous passer un tableau sur la pile en C? – Alexander

1

Cela dépend de l'endroit où vous avez déclaré la variable. Une variable locale (c'est-à-dire, une déclarée sur la pile est limitée par la taille maximale de l'image) Ceci est une limite du compilateur que vous utilisez (et peut généralement être ajustée avec les indicateurs du compilateur).

Un objet alloué dynamiquement (c'est-à-dire, un objet qui est sur le tas) est limité par la quantité de mémoire disponible. C'est une propriété du système d'exploitation (et techniquement plus grande si vous avez un système d'exploitation intelligent).

0

Il est peu probable que vous rencontriez un débordement de pile avec du C compilé non threadé, sauf si vous faites quelque chose de particulièrement flagrant comme une récursivité incontrôlée ou une fuite de mémoire cosmique. Cependant, votre simulateur a probablement un paquet de threading qui imposera des limites de taille de pile. Lorsque vous démarrez un nouveau thread, il alloue un morceau de mémoire pour la pile de ce thread. Il est probable que vous puissiez définir un paramètre définissant la taille de la pile par défaut, ou qu'il existe un moyen de développer dynamiquement la pile. Par exemple, pthreads a une fonction pthread_attr_setstacksize() que vous appelez avant de démarrer un nouveau thread pour définir sa taille. Votre simulateur peut utiliser ou non des pthreads. Consultez la documentation de référence de votre simulateur.

1

De nombreux systèmes d'exploitation développent dynamiquement la pile au fur et à mesure que vous l'utilisez. Lorsque vous commencez à écrire dans une adresse mémoire juste au-delà de la pile, le système d'exploitation suppose que votre pile a augmenté et alloue une page supplémentaire (généralement 4096Kib sur x86 - exactement 1024 ints).

Le problème est, sur le x86 (et d'autres architectures) pousse la pile vers le bas mais matrices C pousser vers le haut . Cela signifie que si vous accédez au démarrer d'un grand tableau, vous accéderez à la mémoire située à plus d'une page du bord de la pile.

Si vous initialisez votre tableau à 0 à partir de la fin du tableau (c'est exact, faites une boucle for pour le faire), les erreurs peuvent disparaître. Si c'est le cas, c'est effectivement le problème.

Vous pourriez être en mesure de trouver des fonctions API OS pour forcer l'allocation de la pile, ou des pragmas/drapeaux du compilateur. Je ne suis pas sûr de savoir comment cela peut être fait de façon portative, sauf bien sûr pour l'utilisation de malloc() et free()!

Questions connexes