web-dev-qa-db-fra.com

Expliquer le concept d'un cadre de pile en un mot

Il semble que l’idée de pile d’appels apparaisse dans la conception du langage de programmation. Mais je ne trouve pas (probablement, je ne cherche pas assez fort) une explication décente de ce que frame de pile est.

Je voudrais donc demander à quelqu'un de me l'expliquer en quelques mots.

168
ikostia

Un cadre de pile est un cadre de données qui est poussé sur la pile. Dans le cas d'une pile d'appels, un cadre de pile représenterait un appel de fonction et ses données d'argument.

Si je me souviens bien, l'adresse de retour de la fonction est d'abord placée dans la pile, puis les arguments et l'espace pour les variables locales. Ensemble, ils forment le "cadre", bien que cela dépende probablement de l'architecture. Le processeur sait combien d'octets se trouvent dans chaque image et déplace le pointeur de pile en conséquence, au fur et à mesure que les images sont déplacées et extraites de la pile.

MODIFIER:

Il existe une grande différence entre les piles d'appels de niveau supérieur et la pile d'appels du processeur.

Lorsque nous parlons de la pile d'appels d'un processeur, nous parlons d'utiliser des adresses et des valeurs au niveau octet/mot dans le code de l'assembly ou de la machine. Il y a des "piles d'appels" lorsqu'on parle de langages de niveau supérieur, mais il s'agit d'un outil de débogage/exécution géré par l'environnement d'exécution afin que vous puissiez enregistrer ce qui ne va pas avec votre programme (à un niveau élevé). À ce niveau, les noms de ligne et les noms de méthodes et de classes sont souvent connus. Au moment où le processeur obtient le code, il n'a absolument aucune notion de ces choses.

166
Tony R

Si vous comprenez très bien la pile, vous comprendrez comment la mémoire fonctionne dans le programme et si vous comprenez le fonctionnement de la mémoire dans le programme, vous comprendrez comment la fonction est stockée dans le programme et si vous comprenez comment la fonction est stockée dans le programme, vous comprendrez comment fonctionne la fonction récursive et si vous comprenez le fonctionnement de la fonction récursive, vous comprendrez le fonctionnement du compilateur et, si vous comprenez le fonctionnement du compilateur, votre esprit fonctionnera comme un compilateur et vous pourrez déboguer tout programme très facilement

Laissez-moi vous expliquer comment fonctionne la pile:

Vous devez d’abord savoir comment la fonction est stockée dans la pile:

Le tas stocke les valeurs d'allocation de mémoire dynamique. Empiler des valeurs d'allocation et de suppression automatiques.

enter image description here

Comprenons avec l'exemple:

def hello(x):
    if x==1:
        return "op"
    else:
        u=1
        e=12
        s=hello(x-1)
        e+=1
        print(s)
        print(x)
        u+=1
    return e

hello(4)

Maintenant, comprenez les parties de ce programme:

enter image description here

Voyons maintenant ce qu'est la pile et quelles sont les parties de la pile:

enter image description here

Allocation de la pile:

Rappelez-vous une chose si une fonction est “return”, peu importe si elle a chargé toutes ses variables locales ou quoi que ce soit qui retournera immédiatement de la pile à son frame de pile. Cela signifie que quand une fonction récursive obtient la condition de base et que nous mettons retour après condition de sorte que la condition de base n’attend pas pour charger les variables locales situées dans la partie "else" du programme, elle retournera immédiatement la trame courante de la pile et maintenant si une trame retourne la prochaine image est dans l'enregistrement d'activation. Voir cela dans la pratique:

enter image description here

Deallocation du bloc:

Alors maintenant, chaque fois qu'une fonction trouve l'instruction return, elle supprime l'image actuelle de la pile.

en revenant de la pile, la valeur retournera dans l’ordre inverse de celui dans lequel ils ont été alloués.

enter image description here

57
Aaditya Ura

Une conclusion rapide. Peut-être que quelqu'un a une meilleure explication.

Une pile d'appels est composée d'un ou de plusieurs cadres de pile. Chaque trame de pile correspond à un appel à une fonction ou à une procédure qui ne s'est pas encore terminée avec un retour.

Pour utiliser un cadre de pile, un thread conserve deux pointeurs, l'un s'appelle le pointeur de pile (SP) et l'autre le pointeur de trame (FP). SP pointe toujours vers le "haut" de la pile, et FP pointe toujours vers le "haut" du cadre. De plus, le fil de discussion conserve également un compteur de programme (PC) qui pointe vers la prochaine instruction à exécuter.

Les éléments suivants sont stockés dans la pile: variables locales et temporaires, paramètres actuels de l’instruction en cours (procédure, fonction, etc.)

Il existe différentes conventions d’appel concernant le nettoyage de la pile.

41
ervinbosenbacher

"Une pile d'appels est composée de cadres de pile ..." - Wikipedia

Un cadre de pile est une chose que vous mettez sur la pile. Ce sont des structures de données contenant des informations sur les sous-routines à appeler.

14
Waleed Khan

Les programmeurs peuvent se poser des questions sur les cadres de pile non pas au sens large (qu’il s’agit d’une entité unique dans la pile servant uniquement un appel de fonction et conservant une adresse de retour, des arguments et des variables locales), mais dans un sens étroit - lorsque le terme stack frames est mentionné dans le contexte des options du compilateur.

Que l’auteur de la question l’ait voulu ou non, mais le concept de cadre de pile du point de vue des options du compilateur est une question très importante, qui n’est pas couverte par les autres réponses ici.

Par exemple, le compilateur Microsoft Visual Studio 2015 C/C++ a l'option suivante liée à stack frames:

  • / Oy (Omission Frame-Pointer Omission)

GCC ont les suivants:

  • -fomit-frame-pointeur (Ne conservez pas le pointeur d'image dans un registre pour les fonctions qui n'en ont pas besoin. Ceci évite les instructions pour enregistrer, configurer et restaurer les pointeurs d'image; il permet également de créer un registre supplémentaire dans de nombreuses fonctions. )

Les compilateurs Intel C++ ont les caractéristiques suivantes:

  • -fomit-frame-pointer (Détermine si EBP est utilisé comme registre à usage général dans les optimisations)

qui a l'alias suivant:

  • / Oy

Delphi a l'option de ligne de commande suivante:

  • - $ W + (Générer des cadres de pile)

En ce sens spécifique, du point de vue du compilateur, un cadre de pile est simplement le code d'entrée et de sortie de la routine, qui place une ancre dans la pile - qui peut également être utilisé pour le débogage et la gestion des exceptions. . Les outils de débogage peuvent analyser les données de la pile et utiliser ces ancres pour effectuer un retour arrière, tout en localisant call sites dans la pile, c’est-à-dire pour afficher les noms des fonctions dans l’ordre dans lequel elles ont été appelées de manière hiérarchique. Pour l'architecture Intel, c'est Push ebp; mov ebp, esp ou enter pour l’entrée et mov esp, ebp; pop ebp ou leave pour quitter.

C’est la raison pour laquelle il est très important que le programmeur comprenne en quoi un cadre de pile correspond aux options du compilateur - car le compilateur peut décider de générer ou non ce code.

Dans certains cas, le compilateur peut omettre le cadre de pile (code d’entrée et de sortie de la routine) et accéder directement aux variables via le pointeur de pile (SP/ESP/RSP) plutôt que le pointeur de base pratique (BP/ESP/RSP). Conditions d'omission du cadre de la pile, par exemple:

  • la fonction est une fonction feuille (c’est-à-dire une entité finale qui n’appelle pas d’autres fonctions);
  • il n’existe pas de constructions try/finally ou try/except ou similaires, c’est-à-dire qu’aucune exception n’est utilisée;
  • aucune routine n'est appelée avec des paramètres sortants sur la pile;
  • la fonction n'a pas de paramètres;
  • la fonction n'a pas de code d'assemblage en ligne;
  • etc...

L'omission des cadres de pile (code d'entrée et de sortie de la routine) peut rendre le code plus petit et plus rapide, mais peut également affecter négativement la capacité du débogueur à effectuer un suivi des données de la pile et à les afficher au programmeur. Ce sont les options du compilateur qui déterminent dans quelles conditions une fonction doit avoir le code d'entrée et le code de sortie, par exemple: (a) toujours, (b) jamais, (c) si nécessaire (en spécifiant les conditions).

5
Maxim Masiutin