221 votes

Quel est le déroulement de pile?

Quel est le déroulement de pile? Fouillé, mais ne pouvait pas trouver de réponse instructive!

164voto

Nikolai N Fetissov Points 52093

Le déroulement de pile est généralement parlé en relation avec la gestion des exceptions. Voici un exemple:

void func( int x )
{
    char* pleak = new char[1024]; // might be lost => memory leak
    std::string s( "hello world" ); // will be properly destructed

    if ( x ) throw std::runtime_error( "boom" );

    delete [] pleak; // will only get here if x != 0
}

int main()
{
    try
    {
        func( 10 );
    }
    catch ( const std::exception& e )
    {
        return 1;
    }

    return 0;
}

Ici, la mémoire allouée pour l' pleak sera perdu si une exception est levée, alors que la mémoire allouée à l' s sera correctement publiés par std::string destructeur dans tous les cas. Les objets alloués sur la pile sont "déroulé" quand le champ est sorti (ici la portée de la fonction func.) Ceci est fait par le compilateur insertion des appels à des destructeurs de l'automatique (pile) variables.

Maintenant, c'est un concept très puissant menant à la technique dite de RAII, c'est l'Acquisition de Ressources Est d'Initialisation, qui nous aide à gérer les ressources comme la mémoire, de connexions de base de données, descripteurs de fichiers ouverts, etc. en C++.

Maintenant, qui nous permet de fournir exception de garanties de sécurité.

82voto

utnapistim Points 12060

Tout cela se rapporte à C++:

Définition: Comme vous créez des objets de manière statique (sur la pile plutôt que de leur répartition dans le segment de mémoire) et d'effectuer des appels de fonction, ils sont "empilés".

Lorsqu'un champ (tout ce qui est délimitée par { et }) est sorti (en utilisant return XXX;, pour atteindre à la fin de la portée ou de la levée d'une exception) tout à l'intérieur de celui-ci est détruit (les destructeurs sont appelés pour tout). Ce processus de destruction des objets locaux et d'appeler les destructeurs est appelé le déroulement de pile. (La sortie d'un bloc de code à l'aide de goto ne va pas se détendre la pile, qui est l'une des raisons pour lesquelles vous ne devriez jamais utiliser goto en C++).

Vous avez des questions suivantes relatives au déroulement de pile:

  1. en évitant les fuites de mémoire (tout ce qui est allouée dynamiquement qui n'est pas géré par un objet local et nettoyé dans le destructeur sera coulé) - voir le RAII visées par Nikolai, et la documentation de boost::scoped_ptr ou cet exemple de l'utilisation de boost::mutex::scoped_lock.

  2. la cohérence du programme: le C++ spécifications état que vous ne devez jamais jeter une exception avant toute exception existante a été traitée. Cela signifie que la pile processus de déroulement ne doit jamais lever une exception (utiliser uniquement le code ne garantie pas à jeter dans les destructeurs, ou surround tout en les destructeurs avec try { et } catch(...) {}).

Si tout le destructeur déclenche une exception pendant le déroulement de pile vous vous retrouvez dans la terre de comportement indéfini qui pourrait causer votre programme de treminate de façon inattendue (la plupart des communes de comportement) ou de l'univers jusqu'à la fin (en théorie possible, mais n'a pas été observée dans la pratique).

42voto

jrista Points 20950

Dans un sens général, une pile de "détente" est à peu près synonyme de la fin de l'appel de la fonction et de la suite éclatement de la pile.

Toutefois, en particulier dans le cas de C++, le déroulement de pile a à voir avec la façon dont C++ appelle les destructeurs des objets alloués depuis la route de tout bloc de code. Les objets qui ont été créés à l'intérieur du bloc sont libérés dans l'ordre inverse de leur allocation.

14voto

Chris Jester-Young Points 102876

Le déroulement de pile est la plupart du temps C++ concept, comment la pile objets alloués sont détruits lors de son champ d'application est quittée (normalement, ou par le biais d'une exception).

Disons que vous avez ce fragment de code:

void hw() {
    string hello("Hello, ");
    string world("world!\n");
    cout << hello << world;
} // at this point, "world" is destroyed, followed by "hello"

11voto

L. Langó Points 336

J'ai lu un post de blog qui m'a aidé à comprendre.

Quel est le déroulement de pile?

Dans n'importe quelle langue qui prend en charge des fonctions récursives (ie. assez bien tout, sauf le Fortran 77 et Brainf*ck) de la langue d'exécution garde une pile de quelles fonctions sont en cours d'exécution. Le déroulement de pile est un moyen de contrôle, et éventuellement de modifier, la pile.

Pourquoi voudriez-vous faire cela?

La réponse peut sembler évidente, mais il en existe plusieurs, mais subtilement différents, des situations où déroulement est utile ou nécessaire:

  1. Comme une exécution de flux de contrôle mécanisme (les exceptions C++, C longjmp(), etc).
  2. Dans un débogueur, pour montrer à l'utilisateur la pile.
  3. Dans un profiler, de prendre un échantillon de la pile.
  4. À partir du programme lui-même (comme à partir d'un crash gestionnaire de montrer la pile).

Ceux-ci ont subtilement différentes exigences. Certains de ces problèmes sont critiques des performances, certains ne le sont pas. Certains exigent l' capacité à reconstituer les registres partir du cadre extérieur, certains ne le font pas. Mais nous allons entrer dans tous ça en une seconde.

Vous pouvez trouver le post complet ici.

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