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 :

Gestion mémoire correcte ou pas ?


Sujet :

C++

  1. #1
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2005
    Messages
    162
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 162
    Par défaut Gestion mémoire correcte ou pas ?
    Supposons que j'écrive ma propre exception qui dérive de std::exception et que je redéfinisse la fonction what() pour lui faire afficher un message particulier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    const char* what() const throw()
    {
    return "Mon exception";
    }
    Puisque cette fonction retourne un objet const char* alloué sur la pile, je voulais savoir à l'utilisation si la zone pointée par le pointeur retourné par what() sera toujours valide ?
    Par exemple est - ce que pointe toujours sur une zone de mémoire valide sachant que l'on est sorti du scope de la fonction what() ?
    Apparement, ça marche mais j'ai quand même un doute ...

  2. #2
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Je soupçonne (à vérifier), que la valdité du pointeur renvoyé par what() est liée directement à la portée de l'objet exception.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  3. #3
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    C'est ce qui parait hélas le plus logique.
    vandamme > ça donne quoi ?

  4. #4
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2005
    Messages
    162
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 162
    Par défaut
    Non, apparemment, même en dehors de la portée de l'objet exception, la zone pointée est toujours valide.
    Je ne comprends pas bien pourquoi ....

  5. #5
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Parce que l'emplacement mémoire correspondant :
    - provient d'une zone statique de constantes ?
    - n'a pas encore été écrasée par d'autres allocations ? (c'est pas comme si les dandling pointers se repéraient au premier accès après libération)
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  6. #6
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2005
    Messages
    162
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 162
    Par défaut
    Est ce que ça veut dire (dans les 2 cas) que ce type de code est à éviter ?

  7. #7
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Tu renvoies un pointeur vers une chaîne littérale, qui est allouée dans une zone statique en lecture seule.
    Ton code est donc parfaitement valide.

  8. #8
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2005
    Messages
    162
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 162
    Par défaut
    D'accord, je pensais que la chaîne litérale était allouée sur la pile.
    Comme par exemple si je faisais dans la fonction what() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    string s("ERREUR");
    return s.c_str();
    Ce qui, je pense n'est pas valide.

  9. #9
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    * Pas bon dans tous les cas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char const* what() throw () {
        std::string s = ....;
        return s.c_str();
    }
    * Toujours bon
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char const* what() throw () {
        char const* s = "....";
        return s;
    }
    * Bon ... ou pas.
    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
    struct TonException {
        .....
        char const* what() throw () {
            return m_s.c_str();
        }
    private:
        std::string m_s;
    };
     
     
    .... 
    const char * e = 0;
    try { 
        throw TonException(.....);
    } catch (TonException const& ex) {
        const char *s = ex.what(); // OK
        std::cerr << s << "\n"; // OK
        e = s; // OK
        std::cerr << e << "\n"; // OK
    }
    if (e) 
        std::cerr << e << "\n"; // PAS OK
    Quant à stocker le ex.what() dans un pointeur externe à la portée courante, et faire un "throw;" pour relancer l'exception, là je ne suis plus sûr si on peut considérer que l'on attrapera le même object exception dans le gestionnaire du dessus.
    Note: j'ai "simplifié" en attrapant par référence constante et pas par valeur.

    (Enfin, c'est comme cela que je vois les choses)
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  10. #10
    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,

    Il y a effectivement de fortes chances que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    const char* what()
    {
    return "Erreur";
    }
    place la chaine erreur, qui est une constante litérale, dans la partie read-only de la mémoire de l'application, mais y a-t-il la moindre certitude que ce sera le cas

    Le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    string s="Erreur"; /* ou string s("erreur");
    return s.c_str();
    me semble à moi aussi des plus suspect

    Par contre, rien ne t'empeche de déclarer une variable membre à ta classe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    class MonErreur/* :public qquechose */
    {
        public:
            MonErreur(const std::string& error):
                     /* qquechose(...), */data_(error){}
            ~MonErreur() throw(){}
            const char* what() /* throw ()*/
            { return data_.c_str();}
        private:
            std::string data_;
    };
    De cette manière, le char* restera valable au moins jusqu'à destruction de l'objet de type MonErreur, et peut etre un peu apres, selon les aléas du besoin de la mémoire
    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

  11. #11
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2005
    Messages
    162
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 162
    Par défaut
    Citation Envoyé par Luc Hermitte
    * Pas bon dans tous les cas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char const* what() throw () {
        std::string s = ....;
        return s.c_str();
    }
    * Toujours bon
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char const* what() throw () {
        char const* s = "....";
        return s;
    }
    * Bon ... ou pas.
    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
    struct TonException {
        .....
        char const* what() throw () {
            return m_s.c_str();
        }
    private:
        std::string m_s;
    };
     
     
    .... 
    const char * e = 0;
    try { 
        throw TonException(.....);
    } catch (TonException const& ex) {
        const char *s = ex.what(); // OK
        std::cerr << s << "\n"; // OK
        e = s; // OK
        std::cerr << e << "\n"; // OK
    }
    if (e) 
        std::cerr << e << "\n"; // PAS OK
    Quant à stocker le ex.what() dans un pointeur externe à la portée courante, et faire un "throw;" pour relancer l'exception, là je ne suis plus sûr si on peut considérer que l'on attrapera le même object exception dans le gestionnaire du dessus.
    Note: j'ai "simplifié" en attrapant par référence constante et pas par valeur.

    (Enfin, c'est comme cela que je vois les choses)
    Merci pour tes réponses.
    En principe c'est le même objet exception qui se propage, et c'est pourquoi il faut toujours l'attraper par référence pour garder l'objet polymorphe s'il l'est.

  12. #12
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2005
    Messages
    162
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 162
    Par défaut
    Merci pour vos réponses.
    C'est plus clair maintenant.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Python 2.X] gestion erreur correcte ou pas
    Par Thierry_V dans le forum Général Python
    Réponses: 4
    Dernier message: 26/08/2014, 23h14
  2. Gestion des droit, correcte ou pas correct ?
    Par Invité2 dans le forum Langage
    Réponses: 3
    Dernier message: 26/07/2011, 10h52
  3. [D7] Tableau dynamique et Gestion mémoire
    Par Cl@udius dans le forum Langage
    Réponses: 7
    Dernier message: 13/03/2006, 15h16
  4. [Gestion mémoire] SetLength sur TDoubleDynArray
    Par MD Software dans le forum Langage
    Réponses: 14
    Dernier message: 24/04/2005, 21h11
  5. Gestion mémoire des Meshes (LPD3DXMESH)
    Par [Hideki] dans le forum DirectX
    Réponses: 1
    Dernier message: 08/07/2003, 20h34

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