36 votes

Un débordement de pile peut-il entraîner autre chose qu'un défaut de segmentation ?

Dans un programme compilé (disons que C ou C++, mais je pense que cette question pourrait s'étendre à toute non-VM-ish langue avec une pile d'appel) - très souvent, quand vous le débordement de la pile, vous obtenez une erreur de segmentation:

Débordement de pile est [un] cause, faute de segmentation est le résultat.

Est-ce toujours le cas? Peut un débordement de la pile, les autres types de programme/OS comportement?

Je demande également au sujet de la non-Linux, non les Os Windows et non du matériel X86. (Bien sûr, si vous n'avez pas de matériel de protection de la mémoire ou de l'OS de soutien de elle (par exemple, MS-DOS), alors il n'y a pas une telle chose comme une erreur de segmentation; je veux parler des cas où vous pourriez obtenir une erreur de segmentation, mais quelque chose se passe).

Remarque: Supposons que, à moins que le dépassement de pile, le programme est valide et n'essayez pas d'accéder à des tableaux delà de leurs limites, de déréférencement de pointeurs invalides, etc.

31voto

Dietrich Epp Points 72865

Oui, même sur un standard de l'OS (Linux) et du matériel standard (x86).

void f(void) {
    char arr[BIG_NUMBER];
    arr[0] = 0; // stack overflow
}

Notez que sur x86, la pile grandit vers le bas, de sorte que nous assignant au début du tableau pour déclencher le dépassement de capacité. Les avertissements habituels s'appliquent... le comportement exact dépend de plusieurs facteurs que sont discutés dans cette réponse, y compris les détails de votre compilateur C.

Si le BIG_NUMBER est à peine assez grand pour dépassement de capacité, vous allez courir dans la pile de garde et d'obtenir une erreur de segmentation. C'est ce que la pile de la garde est là pour, et il peut être aussi petit qu'une seule 4 KiB page (mais pas plus petit, et ce 4 Kio taille est utilisé avant Linux 4.12) ou il peut être plus grand (1 MiB par défaut sur Linux 4.12, voir mm: grande pile de la garde d'écart), mais c'est toujours une taille particulière.

Si BIG_NUMBER est suffisamment grand, le dépassement peut sauter par-dessus la pile de la garde et de la terre sur un autre morceau de la mémoire, peut-être la mémoire qui est valide. Cela peut entraîner votre programme se comporter de manière incorrecte, mais ne pas s'écraser, ce qui est essentiellement le pire des cas: nous voulons que nos programmes de planter quand ils sont incorrects, plutôt que de faire quelque chose d'involontaire.

7voto

Jesper Juhl Points 14756

Une chose est ce qui se passe au moment de l'exécution lorsque vous débordement de la pile, qui peut être beaucoup de choses. Y compris, mais sans s'y limiter, faute de segmentation, d'écraser des variables suivant ce que vous débordement, provoquant une instruction illégale, rien du tout et beaucoup plus. Le "vieux" de la gamme classic de casser La Pile Pour le Plaisir Et le Profit décrit un grand nombre de façons on peut "s'amuser" avec ce genre de choses.

Une autre chose est ce qui peut arriver au moment de la compilation. En C et en C++, de l'écriture au-delà d'un tableau ou de dépasser la taille de la pile est un Comportement indéterminé et lorsqu'un programme contient UB n'importe où le compilateur est fondamentalement libre de faire ce qu'il veut à toute partie de votre programme. Et les compilateurs modernes sont en train de devenir très agressif dans l'exploitation de l'AC pour les fins d'optimisation - souvent en supposant que l'UB n'arrive jamais, les conduisant à simplement supprimer le code contenant de l'UB ou de causer une branche de toujours ou de ne pas être pris parce que l'alternative serait la cause de l'AC. Parfois, le compilateur va introduire le voyage dans le temps ou appeler une fonction qui n'a jamais été appelée dans le code source , et bien d'autres choses qui peuvent causer vraiment déroutant au moment de l'exécution de comportement.

Voir aussi:

Ce Que Tout Programmeur C Devrait Connaître Un Comportement Indéfini #1/3

Ce Que Tout Programmeur C Devrait Connaître Un Comportement Indéfini #2/3

Ce Que Tout Programmeur C Devrait Connaître Un Comportement Indéfini #3/3

Un Guide de Comportement Indéfini en C et C++, Partie 1

Un Guide de Comportement Indéfini en C et C++, Partie 2

Un Guide de Comportement Indéfini en C et C++, Partie 3

6voto

Graham Points 461

D'autres réponses ont couvert du côté du PC assez bien. Je reviendrai sur certaines de ces questions dans le monde embarqué.

Code incorporé ne avoir quelque chose de similaire à une erreur de segmentation. Le Code est stocké dans une sorte de stockage non-volatile (généralement flash ces jours-ci, mais une sorte de ROM ou PROM dans le passé). L'écriture de ce les besoins d'opérations spéciales pour le configurer, pour une normale de l'accès à la mémoire puisse lire mais pas écrire. En outre, les processeurs ont généralement de grandes lacunes dans leur mémoire les cartes. Si le processeur reçoit une demande d'écriture de la mémoire qui est en lecture seule, ou si elle devient une opération de lecture ou d'écriture demande une adresse qui n'existe pas physiquement, le processeur est généralement de jeter un matériel d'exception. Si vous avez un débogueur connecté, vous pouvez vérifier l'état du système à trouver ce qui n'allait pas, comme avec un core dump.

Il n'y a aucune garantie que ce sera le cas pour un débordement de pile si. La pile peut être placé n'importe où dans la mémoire RAM, et ce sera généralement avec d'autres variables. Le résultat de débordement de pile sera généralement à corrompre ces variables.

Si votre application utilise également des tas (allocation dynamique), puis il est courant d'attribuer une section de la mémoire où la pile commence au bas de cet article et s'étend vers le haut, et le tas commence au sommet de cette section et s'élargit vers le bas. Clairement, cela signifie allouée dynamiquement des données sera la première victime.

Si vous êtes malchanceux, vous ne pouvez pas le même avis quand il arrive, et puis vous avez besoin de savoir pourquoi votre code n'est pas se comporter correctement. Le plus ironique cas, si les données écrasé est un pointeur, alors vous pouvez toujours obtenir un matériel d'exception lorsque le pointeur de la tente d'accéder à la mémoire invalide - mais ce sera peu de temps après le débordement de la pile et le naturel hypothèse sera généralement que c'est un bug dans votre code.

Code embarqué a un modèle commun pour faire face à cela, qui est de "filigrane" de la pile par l'initialisation de chaque octet d'une valeur connue. Parfois, le compilateur peut le faire; ou parfois, vous devrez peut-être mettre en œuvre vous-même dans le code de démarrage avant le main(). Vous pouvez regarder en arrière à partir de la fin de la pile de trouver où il n'est plus fixé à cette valeur, à quel point vous connaissez la haute-eau de marque pour l'utilisation des piles; ou s'il est incorrect, alors vous savez que vous avez un dépassement de capacité. Il est courant (et de bonnes pratiques) pour les applications intégrées à ce sondage en continu comme une opération en arrière-plan, et pour être en mesure de signaler des fins de diagnostic.

L'avoir rendu possible le suivi de l'utilisation des piles, la plupart des entreprises, un acceptable pire-cas de la marge pour éviter les débordements. C'est généralement quelque part de 75% à 90%, mais il y aura toujours des pièces de rechange. Non seulement cela permet pour la possibilité qu'il y a de pire pire des cas, vous n'avez pas encore vu, mais il rend aussi la vie plus facile pour le développement futur quand le nouveau code doit être ajouté qui utilise le plus de la pile.

3voto

haccks Points 33022

Stackoverflow est l'une des nombreuses raisons pour le comportement indéfini d'un programme. Dans ce cas, vous pouvez obtenir un résultat attendu ou un défaut de segmentation ou votre disque dur pourrait être effacé, etc. Ne vous attendez pas à un comportement défini parce qu'il s'agit d'un comportement indéfini.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X