2010-08-26 7 views
6

Donc, à partir de ma précédente question memmove, je voudrais savoir comment trouver la direction de la croissance de la pile.direction de la croissance de la pile

void stackDirection(int* i) 
    { 

    int j; 

    if(&j>i) 
     cout<<"Stack is growing up \n"<<endl; 
    else 
     cout<<"Stack is growing down \n"<<endl; 


    } 
    int main() 
    {  
     int i=1; 

     stackDirtection(&i); 

} 
+2

Et votre code ne fonctionne pas, ou quel est le problème? – nothrow

+0

Le problème est que je ne peux pas dire si ce code est correct – brett

+0

imo un meilleur test serait séquentiel appels _alloca, comme les pointeurs de la pile seraient dans le même cadre de la pile, et ne seraient pas soumis à des optimisations – Necrolis

Répondre

13

La pile ne peut se développer vers le haut ou vers le bas.

Chaque trame de pile peut potentiellement être allouée à des points aléatoires à l'intérieur du tas.
Ceci est réellement fait dans plusieurs systèmes d'exploitation pour essayer d'empêcher la destruction de la pile par un code malveillant. Le concept d'une pile qui pousse vers le tas est un moyen simple d'enseigner le concept de pile (et bien sûr, les premières mises en œuvre ont fonctionné de cette façon car il était simple (pas besoin de faire quelque chose de plus difficile que personne n'essaie de vous briser)).

+0

@Martin Stack est créé sur le tas? Je suppose l'avoir? OS sépare la pile du tas droit et les divise en pages droite? Comment cela peut-il être dépendant de l'architecture? Parce que ce que je veux dire ici, ce sont des adresses logiques correctes et ces adresses logiques sont juste dépendantes du compilateur? – brett

+0

@Brett: Du point de vue du matériel, toute la mémoire est juste de la mémoire. L'OS peut alors choisir de faire ce qu'il veut. – Potatoswatter

+1

@brett: Dans l'ancien temps, la pile et le tas étaient des entités séparées et croissaient conceptuellement l'un vers l'autre. Mais c'était plutôt facile à corrompre et provoquer l'exécution de code malveillant. Donc, certaines personnes intelligentes ont un peu réfléchi. Maintenant, une pile est juste une série d'images (une pour chaque appel de fonction). Il n'y a pas de raison technique pour laquelle ils doivent aller l'un après l'autre (comme le lien actuel a un lien avec le dernier). Alors pourquoi ne pas simplement allouer des cadres de pile dans le tas en utilisant des routines normales de gestion de la mémoire. Conceptuellement: Le déroulement de la pile libère l'image en cours et suit la chaîne. –

0

Votre fonction dépend du paramètre int * qui peut pointer n'importe où, et aussi être NULL. Il est préférable de comparer les adresses de deux variables locales.

+0

Le compilateur est libre d'allouer des variables locales dans n'importe quel ordre. Oui, il va les construire et les détruire dans le bon ordre, mais il peut leur allouer de l'espace où il veut. – sharptooth

1

Des expériences comme celles-ci ne sont pas fiables, car vous pouvez rencontrer des exceptions. L'optimiseur peut vous déranger ou le système peut utiliser des registres pour les paramètres. Si vous connaissez vraiment la direction de la pile, lisez le manuel de votre processeur. Néanmoins, à moins que vous n'écriviez un système d'exploitation ou quelque chose de vraiment bas niveau, si vous avez besoin de connaître la direction de la pile, vous faites probablement quelque chose de moche et horrible et devriez vraiment reconsidérer vos méthodes.

0

Ceci est en dehors de la portée de la norme C++. Il s'agit d'un comportement défini par l'implémentation et dépend probablement de l'architecture spécifique du système d'exploitation/du processeur.

Il est préférable de ne pas compter sur de tels détails, sauf si vous êtes concerné par le piratage ETHICAL :) et/ou si vous n'êtes pas vraiment concerné par la portabilité

0

Tenir compte de la réécriture suivante, qui expose une façon dont un compilateur peut mettre en œuvre votre code:

stackDirection void (int * i) { struct {__vars_stackDirection int j; } * __ stackframe_stackDirection = malloc (sizeof (int));

if(&(__stackframe.j) > i) 
    cout<<"Stack is growing up \n"<<endl; 
else 
    cout<<"Stack is growing down \n"<<endl; 

} int main() {
struct __vars_main {int i ; } * __ stackframe_main = malloc (sizeof (int));

stackDirection(&(__stackframe.i)); 

}

Vous devez accepter que __stackframe_stackDirection et __stackframe_main sera essentiellement aléatoire. La pile peut augmenter ou diminuer. Pire, vous supposez un modèle linéarisé. Soit a<b, b<a, or a==b. Mais pour les pointeurs, cela ne tient pas. Les trois comparaisons a<b, b<a and a==b peuvent être fausses en même temps.

Questions connexes