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

Langage C++ Discussion :

Unique_ptr : Orwell Dev-C++ fait-il revivre les morts ?


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 159
    Par défaut Unique_ptr : Orwell Dev-C++ fait-il revivre les morts ?
    Bonjour à tous,

    Je suis en train de me former à l'utilisation des smart pointers de la STL et je faisais des tests sur unique_ptr. Je développe sous Orwell Dev-C++, un fork de Dev-C++ qui supporte C++11.

    J'ai une classe basique qui affiche des phrases dans la console pour contrôler ce qui se passe au niveau des constructions, destructions...

    Voilà le .h
    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
     
    #ifndef _TEST_
    #define _TEST
     
    class Test
    {
    	public:
    		Test();
    		Test(int i);
     
    		void aboie();
     
    		~Test();
    };
     
    #endif
    et le .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
    #include "Test.h"
    #include<iostream>
     
    Test::Test()
    {
    	std::cout << this << ": Construction basique." << std::endl;
    };
     
    Test::Test(int i)
    {
    	std::cout << this << ": Construction parametree:" << i << std::endl;
    };
     
    void Test::aboie()
    {
    	std::cout << this << ": Waf waf !" << std::endl;
    }
     
    Test::~Test()
    {
    	std::cout << this << ": Destruction" << std::endl;
    }
    Rien d'intelligent là dedans, je découvre...

    Maintenant, j'ai voulu faire planter le programme pour voir ce qui se passait quand on appelait une méthode de l'objet géré après un release.

    Voilà mon main :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    #include "Test.h"
    #include <memory>
     
    int main()
    {
    	std::unique_ptr<Test> t(new Test), t2;
    	t->aboie();
    	t.release();
    	t->aboie();
    	return 0;
    }
    et voilà le résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    0x8b1818: Construction basique.
    0x8b1818: Waf waf !
    0: Waf waf !
     
    --------------------------------
    Process exited with return value 0
    Press any key to continue . . .
    J'ai donc le pointeur NULL qui aboie joyeusement... J'ai très peur de cette voix d'outre tombe !!

    Donc, est-ce un comportement normal ou alors une mauvaise implémentation de la part du compilateur d'Orwell Dev-C++.
    Ou pour parler autrement, dois-je me séparer directement de cet IDE que j'apprécie fortement ?

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Première chose : Quand tu fais ce genre de classes de test, n'oublie jamais les constructeurs de copie et opérateur=, sinon, tu risques de na pas comprendre ce qui se passer (ou interdit ces opérations). Et comme tu es en C++11, pense aussi aux versions "move" de ces opérations.

    Ensuite, appeler une fonction sur un pointeur nul est un comportement indéfini. Qui peut donc TOUT faire, y compris te donner l'impression que ça marche ! Ce qui est le cas ici. Si tu veux déjà avoir plus de chances que ça plante, essayé d'accéder à des données membre de ta classe dans cette fonction.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    159
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 159
    Par défaut
    Oui, je vois,

    J'ai compris le non-plantage.
    Vu que je ne fais qu'un affichage de texte + une valeur de pointeur, je n'essaye pas d’accéder à une adresse mémoire invalide et donc je ne plante pas.

    Merci.

    EDIT: c'est bon, j'ai réussi à tout casser !!

  4. #4
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Première chose : Quand tu fais ce genre de classes de test, n'oublie jamais les constructeurs de copie et opérateur=, sinon, tu risques de na pas comprendre ce qui se passer (ou interdit ces opérations). Et comme tu es en C++11, pense aussi aux versions "move" de ces opérations.

    Ensuite, appeler une fonction sur un pointeur nul est un comportement indéfini. Qui peut donc TOUT faire, y compris te donner l'impression que ça marche ! Ce qui est le cas ici. Si tu veux déjà avoir plus de chances que ça plante, essayé d'accéder à des données membre de ta classe dans cette fonction.
    Je confirme cette interprétation. En fait, si tu réécris ton code C++ en son équivalent procédural (genre C, mais en C++), tu obtiens :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void Test_aboie(Test *_this)
    {
        std::cout << _this << "waf waf !" << std::endl;
    }
    Nulle part tu ne provoque d'accès qui va faire mal à ton programme. Il faut bien comprendre que dans la plupart des ABI (abstract binary interface), et notamment sur celles proposées par g++ et Visual C++, une méthode n'est rien d'autre qu'une fonction à laquelle on passe un paramètre caché "this" (généralement via le registre ecx sur x86). Si la fonction ne fait rien de dangereux, alors elle peut être appelée avec this == NULL ou même this == 0xdeadbeef (32 bits) sans pour autant planter. Maintenant, si tu essaie d'accéder en lecture ou en écriture à une variable membre de la classe, tu vas avoir des soucis, puisque ton code va ressembler à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void Test_aboie(Test *_this)
    {
        std::cout << _this << "waf waf ! " << _this->m_var << std::endl;
    }
    Et là, l'accès à m_var va faire mal, car son adresse est égale à (this + offset de m_var dans Test), ce qui ne sera pas une adresse valide si _this n'en est pas une (ou alors, par un coup de chance infâme).

    Petite chose supplémentaire : si c'est l'IDE que tu apprécie, alors ne te pose pas de question - d'autant plus quand c'est le compilateur qui fait des choses "étranges" (mais largement compréhensible dans ce cas particulier). A la limite, change le compilateur (mais tu n'en trouveras pas qui auront un comportement standard, puisque tu lui demande justement de faire quelque chose que le standard ne veut pas prévoir (il ne va pas s'amuser à prévoir toutes les mauvaises utilisations).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

Discussions similaires

  1. Réponses: 5
    Dernier message: 10/10/2006, 18h39
  2. Comment fait ça avec les pointeurs, la fonction et les struc
    Par mahdianis dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 24/02/2006, 18h01
  3. Scroll comboBox ne fait pas défiler les ItemData !
    Par Tchupacabra dans le forum IHM
    Réponses: 4
    Dernier message: 09/12/2005, 09h13
  4. Dev c++ en rade sur les pointeurs ?...
    Par Magicien d'Oz dans le forum C
    Réponses: 17
    Dernier message: 13/10/2005, 19h38
  5. Dev C++ (Bien seulement pour les debutants)?
    Par Frazeks dans le forum Dev-C++
    Réponses: 3
    Dernier message: 20/09/2005, 13h41

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