IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Différence d'adresse mémoire stack et heap


Sujet :

C++

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 7
    Points : 1
    Points
    1
    Par défaut Différence d'adresse mémoire stack et heap
    Bonjour,

    Je ne comprends pas pourquoi les adresses mémoires retournée pour une variable sur la pile et allouée dynamiquement dans un même processus ne sont pas semblables.

    Le programme en fin de message donne le résultat suivant:

    adresse stack : 0x7fff3a3c2274
    adresse heap : 0x602010


    Pourquoi l'adresse du heap n'est pas en 0x7fff3a3cXXXX
    Le 0x602010 s'agit-il d'une clé associée à une "vraie" adresse mémoire, au quel cas qu'on fait un memcpy() sur un bout de mémoire dynamique ai-je pour chaque octet ce mécanisme de traduction de la clé vers la "vraie" adresse (je serai surpris, d'où mon incompréhension) ?

    Merci à vous

    Voici le programme qui me génère le message en gras donné plus haut.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    #include <stdlib.h>
    #include <iostream>
     
    using namespace std;
     
    int main(void)
    {
        int valeur;
        int * pointeur = new int();
        cout << "adresse stack : " << &valeur  << endl;
        cout << "adresse heap : " << pointeur << endl;
     
        return 0;
    }

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    327
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Janvier 2009
    Messages : 327
    Points : 402
    Points
    402
    Par défaut
    Bonjour,
    Tes deux objets sont différents.
    int valeur; est construit avec le contructeur par default du int. Il est dans la pile.
    int * pointeur = new int(); ca c'est un pointeur qui référence un objet int dans le tas;
    Les deux objets n'ont rien à voir. C'est pour cela qu'ils n'ont pas la même adresse.
    J'espère que c'est assez clair et qe cela pourra t'aider.
    A bientôt

  3. #3
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par wakan Voir le message
    Bonjour,
    Tes deux objets sont différents.
    int valeur; est construit avec le contructeur par default du int. Il est dans la pile.
    int * pointeur = new int(); ca c'est un pointeur qui référence un objet int dans le tas;
    Les deux objets n'ont rien à voir. C'est pour cela qu'ils n'ont pas la même adresse.
    J'espère que c'est assez clair et qe cela pourra t'aider.
    A bientôt
    C'est très clair mais ça ne m'avance pas (et accessoirement c'était dit dans mon post), car ma question est justement de comprendre la différence entre c'est deux adresses alors même que pour moi elle était dans l'espace mémoire du processus et donc avaient la même base.

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    N'oublie pas que les adresses mémoires sont virtuelles, donc que tes pointeurs sont des adresses vues "du processus".

    Et apparemment, sur ton système, la pile commence tout en haut de la moitié "utilisateur" (inférieure à 0x8000000000000000) de la mémoire virtuelle du processus, tandis que le tas commence plus proche du bas...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    1/ ce ne sont pas des @ physiques à moins que tu sois sous Windows 3.0
    2/Il n'y a pas de raison que la pile et le tas soit à la même place. Tu peux voir dans ce tuto (qui porte sur les problèmes de dépassement de capacité de la pile), le premier chapitre (page 9) présente la mapping mémoire pour un processus sous linux.

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Il me parait bizarre, ce diagramme: Notamment pour la position de argc et argv...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Il est surtout intéressant pour montrer le principe.

  8. #8
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    N'oublie pas que les adresses mémoires sont virtuelles, donc que tes pointeurs sont des adresses vues "du processus".

    Et apparemment, sur ton système, la pile commence tout en haut de la moitié "utilisateur" (inférieure à 0x8000000000000000) de la mémoire virtuelle du processus, tandis que le tas commence plus proche du bas...
    Merci pour cette réponse.
    Effectivement, ces adresses sont virtuelles, toutefois il y a deux points qui m'échappent:
    + Pourquoi laisser un espace de 127 Tera octets entre le bas de la stack et le haut du tas? Je veux bien qu'on est des systèmes avec potentiellement beaucoup de mémoire enfin il y a encore des limites
    + Enfin si je relance 100 fois ce programme, 100 fois j'aurai la même adresse pour le bout de mémoire allouée dynamiquement alors que l'adresse sur la pile sera 100 fois différente, une idée ?

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Comme je dis: La pile commence tout en haut, c'est traditionnel.

    Par contre, je suis vraiment surpris que la pile change d'adresse virtuelle à chaque exécution...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Comme je dis: La pile commence tout en haut, c'est traditionnel.

    Par contre, je suis vraiment surpris que la pile change d'adresse virtuelle à chaque exécution...
    J'ai testé sur deux archis différentes (Intel Duo core, VIA ULV), je constate que les deux adresses des variables, sur la stack l'autre dans le tas varie à chaque exécution, ce qui tout compte est parfaitement logique puisque je doute que le système soit capable de placer deux fois de suite le processus au même endroit en mémoire, non?

    Non du coup ce qui m'étonne plus c'est d'avoir constaté sur troisième machine différente des deux précédentes que l'adresse de la variable sur la stack était toujours la même quelque soit le lancement.

    PS : Je viens de faire le teste dans cygwin (""environnement"" Unix sous Windows) et là je peux constater que les adresses des deux variables sont toujours les mêmes quelque soit le nombre de lancement.
    Mais il est probable que Cygwin gère lui même l'adresse mémoire fait par ses processus.

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par easyquizz Voir le message
    je doute que le système soit capable de placer deux fois de suite le processus au même endroit en mémoire, non?
    Au contraire: Vu du processus, c'est même plus logique d'avoir tout le temps les mêmes adresses virtuelles que l'inverse.
    Bien sûr, les "adresses réelles" seront différentes, mais ça, seul le kernel le sait: Aucun processus ne le voit...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Au contraire: Vu du processus, c'est même plus logique d'avoir tout le temps les mêmes adresses virtuelles que l'inverse.
    Bien sûr, les "adresses réelles" seront différentes, mais ça, seul le kernel le sait: Aucun processus ne le voit...
    En fait j'ai trouvé un début d'explication qui me semble raisonnable:
    + D'une exécution à une autre l'adresse du haut de la stack et du bas du heap qui varient afin de compliquer la tache d'un hackeur qui, sinon pourrait retrouver plus facilement un contenu en mémoire.
    + Naturellement cette technique serait définie par le système.

    Est-ce plausible?

  13. #13
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Citation Envoyé par easyquizz Voir le message
    En fait j'ai trouvé un début d'explication qui me semble raisonnable:
    + D'une exécution à une autre l'adresse du haut de la stack et du bas du heap qui varient afin de compliquer la tache d'un hackeur qui, sinon pourrait retrouver plus facilement un contenu en mémoire.
    + Naturellement cette technique serait définie par le système.

    Est-ce plausible?
    Imaginons un programme qui fait une très grosse utilisation de la pile. Cela voudrait dire que 2 exécutions de ce même programme n'auraient pas forcément le même résultat.
    • La première fois cela plante parce que le hasard a voulut que l'adresse du haut de la pile soit 'assez' bas et donc au final, pas assez de pile
    • La seconde fois, cela passe parce que le hasard a voulut que l'adresse du haut de la pile soit 'assez' haut et donc au final, il y avait assez de pile

    J'y crois pas trop. En général, en informatique, on essaye de supprimer les comportements non déterministes.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  14. #14
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    C'est bien possible: Le comportement "Address Space Layout Randomization", quand il est intentionnel, est bien une mesure de sécurité.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  15. #15
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    Imaginons un programme qui fait une très grosse utilisation de la pile. Cela voudrait dire que 2 exécutions de ce même programme n'auraient pas forcément le même résultat.
    • La première fois cela plante parce que le hasard a voulut que l'adresse du haut de la pile soit 'assez' bas et donc au final, pas assez de pile
    • La seconde fois, cela passe parce que le hasard a voulut que l'adresse du haut de la pile soit 'assez' haut et donc au final, il y avait assez de pile

    J'y crois pas trop. En général, en informatique, on essaye de supprimer les comportements non déterministes.
    Un processus connaissant la taille de sa pile au démarrage (cf ulimit -a) sait donc où placer le début de celle-ci afin qu'elle est assez de place. Après rien n'interdirait de faire varier la position de ce début de quelques octets, en continuant de s'assurer qu'on dispose toujours de l'espace nécessaire.
    Du coup on reste déterministe (tant que la taille de la pile est respectée) et on s'assure que personne ne pourra anticiper l'adresse mémoire de la stack ou du tas.

  16. #16
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Je viens de tester ce code sous Windows XP Professionnel 32 bits, compilé avec Microsoft Visual Studio 2008 SP1:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // NouveauPremierTest.c : Defines the entry point for the console application.
    //
     
    #include "stdafx.h"
     
    void TestMem(void)
    {
    	int valeurPile = 42;
    	int *pValeurPile = &valeurPile;
    	int *pValeurTas = malloc(sizeof *pValeurTas);
     
    	printf("Adresse pile : %p\n", (void*)pValeurPile);
    	printf("Adresse tas  : %p\n", (void*)pValeurTas);
     
    	free(pValeurTas);
    }
     
    int _tmain(int argc, _TCHAR* argv[])
    {
    	_tprintf(_T("Hello world!\n"));
    	TestMem();
    	return 0;
    }
    En mode Debug, j'ai systématiquement ces valeurs:
    Code X : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Hello world!
    Adresse pile : 0012FE8C
    Adresse tas  : 0034A1F8
    En Release, j'ai tout le temps celles-ci:
    Code X : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Hello world!
    Adresse pile : 0012FF7C
    Adresse tas  : 00349AD8
    On remarque que dans le cas de ce code et cet OS, la pile est située à des adresses inférieures au tas.
    Aussi, pour confirmer ce que je dis sur la virtualité de la mémoire, j'ai rajouté une pause à la fin du programme avant d'en lancer deux instances : Les résultats n'ont pas changé, chacun voyant sa pile et son tas aux mêmes adresses virtuelles.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  17. #17
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Je viens de tester ce code sous Windows XP Professionnel 32 bits...
    Merci pour ce test qui en ce qui me concerne vient clore ce fil de discussion.
    J'en retiendrai que les adresses virtuelles où sont placés la stack et le tas dépendent des choix retenus par l'OS et de ce qu'autorise les le hardware.
    Et qu'effectivement dans certains cas le système place les places à des positions variables.
    Va juste falloir que je rebosse mes cours sur les segments mémoire et la pagination.

Discussions similaires

  1. Réponses: 16
    Dernier message: 30/05/2006, 18h46
  2. lire la valeur d'une adresse mémoire
    Par ilimo dans le forum Windows
    Réponses: 17
    Dernier message: 11/04/2006, 15h21
  3. PRoblème d'adresse mémoire
    Par pmboutteau dans le forum Access
    Réponses: 11
    Dernier message: 07/04/2006, 11h00
  4. Réponses: 6
    Dernier message: 19/09/2005, 19h48
  5. Differences Stack et Heap
    Par elsargento dans le forum C++
    Réponses: 9
    Dernier message: 26/05/2004, 16h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo