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 :

Vector et création d'objets


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 64
    Points : 40
    Points
    40
    Par défaut Vector et création d'objets
    Bonjour, je reviens avec un vieux problème.

    J'ai une fonction qui crée des objets pour les placer dans un vecteur. Comme tout le monde sait, lorsqu'une fonction se termine elle libère tout ce qui a été déclaré, instancié ainsi que les pointeurs (directs).

    J'aimerais écrire donc ceci de façon moins compliquée et avec un style c++ :

    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
    private :
    vector<CDraw*> images;
     
    ...
     
    void fonction() {
     
            CDraw **draw;
             draw = (CDraw**)malloc(sizeof(CDraw*));
             *draw = new CDraw(true, complet_file.c_str(), coord_, coef_resol);
     
             // We reverse picture on Y axis
             if(orientation_)
                (*draw)->reverse_H_SDL();
     
             images.push_back(*draw);
     
    }

  2. #2
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2012
    Messages : 24
    Points : 22
    Points
    22
    Par défaut
    Bonjours

    Tu te donne du soucis pour rien :

    Lors d'une fonction, on détruis les variables, mais si tu ne fais aucun delete, l'objet sur lequel pointe un pointeur n'est pas détruit :

    un petit code pour l'exemple :
    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
     
     
    using namespace std;
     
    vector<int*> tab;
     
    void fonct(){
        int *i = new int(3);
        tab.push_back(i);
    }
     
    int main()
    {
        fonct();
        int *io = tab[0];
        cout << *io;
        return 0;
    }
    Le code affiche bien... 3, alors que le pointeur i de fonc a été détruit

    Dans cet exemple, j'utilise une variable globale (bouh, pas bien) mais c'est le même principe avec ton vector de CDraw* encapsulé.

    Par contre, si tu fais ce code là :
    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
     
     
    using namespace std;
     
    vector<int*> tab;
     
    void fonct(){
        int *i = new int(3);
        tab.push_back(i);
        delete i;
    }
     
    int main()
    {
        fonct();
        int *io = tab[0];
        cout << *io;
        return 0;
    }
    cela afficheras 0, car l'objet sur lequel pointe le pointeur a été détruit, tu me suis ?

    En espérant t'avoir aidé !

  3. #3
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,
    Citation Envoyé par jetSett Voir le message
    Par contre, si tu fais ce code là :
    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
     
     
    using namespace std;
     
    vector<int*> tab;
     
    void fonct(){
        int *i = new int(3);
        tab.push_back(i);
        delete i;
    }
     
    int main()
    {
        fonct();
        int *io = tab[0];
        cout << *io;
        return 0;
    }
    cela afficheras 0, car l'objet sur lequel pointe le pointeur a été détruit, tu me suis ?

    En espérant t'avoir aidé !
    En fait, il y a surtout énormément de chances pour que ce code se solde par... une erreur de segmentation (ou par l'envoi d'un missile nucléaire ballistique)

    L'adresse "pointée" par le pointeur est bel et bien libérée, mais le (pseudo) destructeur d'un entier ne fait strictement rien.

    Il n'y a donc aucune modification des données qui se trouvent à l'adresse "pointée par" le pointeur

    Par contre, le pointeur qui se trouve dans le tableau pointe effectivement sur une adresse invalide (car la mémoire a été libérée), qui peut, potentiellement, être récupérée pour un usage ultérieur.

    Tout tentative d'accès à ce qui se trouve à cette adresse mémoire se traduira donc par un comportement indéfini (undefined behaviour), et donc au minimum par des résultats incohérents, voir par une erreur de segmentation
    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

  4. #4
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2012
    Messages : 24
    Points : 22
    Points
    22
    Par défaut
    Bonsoir
    En fait, il y a surtout énormément de chances pour que ce code se solde par... une erreur de segmentation
    Oui, j'ai été surpris aussi quand mon programme a affiché cela c'est peut etre le fait que je sois sous Windows... j’essayerais sous linux pour voir, mais en tout cas, j'espère avoir expliqué comment faire à killwin

    Merci à vous

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    280
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 280
    Points : 149
    Points
    149
    Par défaut
    Citation Envoyé par jetSett Voir le message
    Bonsoir


    Oui, j'ai été surpris aussi quand mon programme a affiché cela c'est peut etre le fait que je sois sous Windows... j’essayerais sous linux pour voir, mais en tout cas, j'espère avoir expliqué comment faire à killwin

    Merci à vous
    Je crois que tous dépend de la taille du segment... Sous Linux la mémoire est allouée par pages (4 Ko typiquement) et les programmes utilise des segments composé d'un nombre entier de pages. La protection de la mémoire se fait par le mécanisme de pagination du matériel et par l'OS au moyen de segment logique (Linux n'utilise pas les mécanismes du processeur pour gérer la segmentation). Soit la page correspond à une page allouée soit une exception est levée par le matériel et géré ensuite par l'OS. Donc si tu libère 4 octet (un entier) dans une page de 4 Ko mais que cette page reste encore allouée (pour d'autre variables) tu pourra continuer à accéder à cette donnée sans avoir d'erreur de segmentation (je ne pense pas que l'OS perde du temps a remettre à zéro la zone libérée). En revanche Si la page a été libérée là tu obtiens une erreur de segmentation.
    Bon j'ai un peu résumé mais je crois que c'est a peu près ça...

    Pour s'en convaincre il suffit d'essayer ce programme en C:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include <stdio.h>
     
    int main(){
        char a=1;
        char* p = &a;
        int i;
        for(i=0;i<4096;i++) printf("%hhX\t",*(p+a));
        return 0;
    }
    "Bien qu'on ait du coeur à l'ouvrage,
    L'Art est long et le Temps est court." - CB

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    L'erreur de segmentation existe également sous linux (SIGSEGV)

    Il n'est pas impossible que *nux soit "moins sensible" à ce genre d'erreur, qu'il arrive plus facilement à éviter qu'elle ne survienne (je ne connais pas suffisemment la gestion interne de la mémoire ni de windows ni de *nux pour donner un avis motivé là dessus ), mais l'erreur peut malgré tout survenir, et tu cours le risque qu'elle survienne dés que tu va essayer d'accéder à une adresse mémoire qui aura été libérée.

    En C++, on sait (c'est la norme qui le dit ) que toute tentative en ce sens résultera en un "undefined behaviour" (un comportement indéfini )

    "Peut etre" le comportement permettra-t-il d'obtenir un résultat malgré tout cohérent, "peut etre" occasionnera-t-il une erreur de segmentation, "peut-etre" obtiendras tu des résultats aberrants, "peut etre" lanceras tu un missile intercontinental

    Le gros problème, c'est que si tu teste un même code plusieurs fois d'affilées, il y a de fortes chances pour que le résultat ne soit jamais identique au résultat obtenu la fois d'avant
    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

Discussions similaires

  1. vector et création d'objets
    Par killwin dans le forum C++
    Réponses: 10
    Dernier message: 11/08/2012, 11h13
  2. [PowerBuilder] Création d'objets dynamiques
    Par Béné123456789 dans le forum Powerbuilder
    Réponses: 3
    Dernier message: 12/06/2006, 00h33
  3. [JMenuBar] Création d'objets à la volée
    Par Rampa dans le forum Composants
    Réponses: 5
    Dernier message: 29/06/2005, 13h56
  4. [FLASH MX2004] Création d'objet dynamiquement
    Par noarno dans le forum Flash
    Réponses: 3
    Dernier message: 15/12/2004, 11h00
  5. Comment initialiser un vector à sa création ?
    Par Clad3 dans le forum SL & STL
    Réponses: 7
    Dernier message: 10/12/2004, 15h01

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