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 :

Problème d'adresse de pointeur


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 17
    Par défaut Problème d'adresse de pointeur
    Bonjour les gens !

    Après 8 ans de Java, j'essaie tant bien que mal de me remettre au C++, mais le petit bout de code suivant me pose bien des soucis :

    class1.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    #include "class1.h"
    Class1::Class1() { }
    class2.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    #include "class2.h"
    Class2::Class2() { }
    Class2::~Class2() { }
    main.cpp
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    #include "class1.h"
    #include "class2.h"
    #include <iostream>
    #include <cassert>
     
    void* ptr;
     
    Class1 test1() {
        Class1 class1;
        ptr = &class1;
        return class1;
    }
     
    Class2 test2() {
        Class2 class2;
        ptr = &class2;
        return class2;
    }
     
    int main(int argc, char *argv[]) {
        Class1 class1 = test1();
        assert (ptr != &class1);
        Class2 class2 = test2();
        assert (ptr == &class2);
    }
    Comme vous pouvez le voir aux deux assertions :
    - dans un cas l'instance de Class1 renvoyée par test1() est DIFFERENTE de celle instanciée dans test1()... et je dis ça parce que les adresses en mémoire sont différentes : cf premier "assert".
    - dans l'autre cas, l'instance de Class2 renvoyée par test2() est LA MEME que celle instanciée dans test2() : cf deuxième "assert".

    Pourtant, la seule différence entre Class1 et Class2 est le fait que dans j'ai explicitement défini le destructeur dans Class2 !

    Si quelqu'un pouvait m'expliquer ce comportement curieux, ça m'éviterait de passer une nouvelle nuit blanche

    Merci beaucoup par avance !

  2. #2
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Bonjour,

    Quand tu récupères l'adresse de class1 et de class2 dans test1() et test2(), tu récupères une adresse sur des objets locaux qui sont détruits en sortant de la fonction.

    Donc réutiliser cette adresse après avoir quitté la fonction est un comportement indéfini. Pas besoin de passer des nuits blanches, les résultats n'ont aucune réelle signification et varieront d'un compilateur à l'autre.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 17
    Par défaut
    Effectivement, c'est l'explication la plus plausible... merci pour ton aide Arzar !

  4. #4
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    C'est bizare, chez moi, le code
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    #include <iostream>
    class Class1
    {
        public:
            Class1(){std::cout<<"Construction d'origine"<<std::endl;}
            Class1(Class1 const & )
            {std::cout<<"Construction par copie"<<std::endl;}
            Class1 & operator=(Class1 const & )
            {std::cout<<"affectation avec l'operateur egal"<<std::endl;
             return *this;}
            ~Class1(){std::cout<<"destruction"<<std::endl;}
    };
    Class1 * ptr;
    Class1 test()
    {
        Class1 c;
        std::cout<<"recuperation de l'adresse ("<<std::hex<<&c<<")"<<std::endl;
        ptr = &c;
        return c;
    }
    int main()
    {
        Class1 t= test();
        std::cout<<"adresse de t :"<<&t<<std::endl;
        std::cout<<ptr<<std::endl;
        return 0;
    }
    fonctionne sans aucun problème chez moi (Serait-ce NRVO qui faire des siennes ) avec comme résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    creation d'origine
    recuperation de l'adresse (0x22fd9f)
    adresse de t : 0x22fd9f
    adresse pointee par ptr : 0x22fd9f
    destruction
    On assiste à la destruction (!!!) de l'objet avant sa copie lorsque test renvoie... une référence (ou une référence constante)
    Citation Envoyé par Arzar Voir le message
    Bonjour,

    Quand tu récupères l'adresse de class1 et de class2 dans test1() et test2(), tu récupères une adresse sur des objets locaux qui sont détruits en sortant de la fonction.
    Oui, mais non...

    Les objets identifiés par les variables dans test1 et dans test2 sont... renvoyés par la fonction, et récupérés dans main...

    Tu aurais destruction de l'objet créé dans test1 et dans test2 si tu renvoyais une référence sur celui-ci et non une valeur

    Tu aurais alors copie de... l'objet après sa destruction, et, fatalement, les adresses ne correspondraient pas.
    Donc réutiliser cette adresse après avoir quitté la fonction est un comportement indéfini. Pas besoin de passer des nuits blanches, les résultats n'ont aucune réelle signification et varieront d'un compilateur à l'autre.
    C'est vrai si
    • l'objet n'est pas renvoyé ou si
    • l'objet est renvoyé sous forme d'une référence (éventuellement constante).


    Ceci dit, il ne faut pas confondre: la valeur représentée par ptr peut être considérée comme une valeur valide, parce qu'elle représente, effectivement, une adresse correcte.

    Par contre, ce sont les tentative de déréférencement en dehors de la fonction (en appelant "ce qui est pointé" par le pointeur) qui provoqueront un comportement indéfini, parce que l'adresse correspond à... celle d'un objet qui a été détruit
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    @koala:
    Pourtant, la seule différence entre Class1 et Class2 est le fait que dans j'ai explicitement défini le destructeur dans Class2 !
    En gros tu viens de faire son test avec class2 qui comme lui marche, enlève le destructeur (ou mets le en default) et retestes, apparament c'était ca qui induisait un comportement different

  6. #6
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Je vient de tester, et j'arrive au même résulat, j'ai aussi tester avec d'autre fonction spécial (constructeur), pour voir si c'était pas un comportement spécifique aux POD par exemple.

    Mais apparament la seule condition qui fait échouer l'égalité c'est l'absence d'un destructeur user-define et non default pour la classe et pour toutes les classes de base et des classes des attributs.

  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
    Par défaut
    Salut,
    La réponse d'Arzar était la bonne : comportement indéterminé ! Visual C++ Express et GCC (mingw) ne me donnent pas le même résultat.

Discussions similaires

  1. Réponses: 7
    Dernier message: 04/06/2007, 12h23
  2. [Modbus RTU] Problème d'adresse
    Par virginoue dans le forum Autres langages
    Réponses: 1
    Dernier message: 16/05/2006, 08h33
  3. [VBA-E] Problème d'adresse de liens hypertext
    Par jgfa9 dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 01/12/2005, 11h11
  4. C++ Problème de fonctions et pointeurs
    Par zmatz dans le forum C++
    Réponses: 3
    Dernier message: 01/10/2005, 16h20
  5. [LG]adresse de pointeur
    Par grand's dans le forum Langage
    Réponses: 7
    Dernier message: 29/05/2004, 10h27

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