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 :

[C++] Libération de mémoire de tableaux et de classes


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Par défaut [C++] Libération de mémoire de tableaux et de classes
    Bonsoir,

    J'ouvre ce post car je suis un peu perdu dans ce que je lis sur le net sur la destruction des tableaux et des classes en C++.
    Pour tout vous dire je suis perdu
    Je tiens à préciser que j'ai lu avec attention la FAQ, vous verrez par la suite

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    t_classe* maclasse = new t_classe();
    // .... utilisation de maclasse
    delete maclasse;
    Question 1 : Pourquoi dans la faq de dvp, ils disent qu'il faut utiliser les crochets pour supprimer un objet ?? donc faire un delete [] maclasse;

    Maintenant passons aux tableaux :

    J'utilise un tableau de vector l'un, des plus simples mais j'ai du mal à comprendre comment le détruire sans fuites de mémoire !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    vector<t_ennemie*> ennemies;
     
     
    // pour le détruire je fais :
    for (unsigned int i=0; i<ennemies.size(); i++)
            {
                delete ennemies[i];
            }
    Question 2 : Est ce correcte ? car dans la faq, ils disent que c'est pas bon et qu'il faut utiliser des itérateurs avec des boost, enfin des trucs que j'ai pas du tout compris...
    LIEN : http://cpp.developpez.com/faq/cpp/?p...ssion_elements

    Voilà pour l'instant, je créé actuellement un jeu et les fuites de mémoires doivent être gérées donc c'est important pour moi

    Merci !
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Citation Envoyé par Aspic Voir le message
    Bonsoir,

    J'ouvre ce post car je suis un peu perdu dans ce que je lis sur le net sur la destruction des tableaux et des classes en C++.
    Pour tout vous dire je suis perdu
    Je tiens à préciser que j'ai lu avec attention la FAQ, vous verrez par la suite

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    t_classe* maclasse = new t_classe();
    // .... utilisation de maclasse
    delete maclasse;
    Question 1 : Pourquoi dans la faq de dvp, ils disent qu'il faut utiliser les crochets pour supprimer un objet ?? donc faire un delete [] maclasse;
    Tu as sans doute mal lu, ou alors tu as mis le doigt sur une grosse erreur dans la FAQ...

    Il faut utiliser delete (sans crochets) lorsque tu as alloué la mémoire avec new (sans crochets) et delete[] (avec crochets) lorsque tu as alloué la mémoire avec new[] (avec crochets)

    La première versions (sans crochet) alloue la mémoire pour un objet unique et la seconde (avec crochet) permet d'allouer de la mémoire contigüe pour un certain nombre d'objets (le nombre apparaissant entre les crochets )
    Maintenant passons aux tableaux :
    J'utilise un tableau de vector l'un, des plus simples mais j'ai du mal à comprendre comment le détruire sans fuites de mémoire !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    vector<t_ennemie*> ennemies;
     
     
    // pour le détruire je fais :
    for (unsigned int i=0; i<ennemies.size(); i++)
            {
                delete ennemies[i];
            }
    Déjà, pourquoi utiliser des pointeurs

    Si tu as plusieurs classes qui héritent de t_ennemie, cela peut se justifier, mais si tu n'a pas pour objectif d'utiliser le polymorphisme, cela ne sert stritement à rien
    Question 2 : Est ce correcte ? car dans la faq,
    Si tu utilise des pointeurs, tu dois, effectivement commencer par veiller à libérer la mémoire allouée à ces pointeurs avant de supprimer les éléments, donc, dans l'exemple que tu présente, oui, c'est correct
    ils disent que c'est pas bon et qu'il faut utiliser des itérateurs avec des boost, enfin des trucs que j'ai pas du tout compris...
    LIEN : http://cpp.developpez.com/faq/cpp/?p...ssion_elements
    Attention, la faq présente comment supprimer un / des éléments des différentes collection, mais se base sur l'utilisation de pointeur, et ne parle que de la suppression d'élément (avec éventuellement la sélection d'éléments à supprimer), absolument pas de la libération de la mémoire
    Voilà pour l'instant, je créé actuellement un jeu et les fuites de mémoires doivent être gérées donc c'est important pour moi

    Merci !
    Si tu n'es pas particulièrement à l'aise sur la gestion de la mémoire et, entre autres, sur la détermination du meilleur moment pour libérer la mémoire, tu devrais te tourner vers les pointeurs intelligents.

    L'utilisation de pointeurs nu n'est, en effet, pas particulièrement conseillée et, il faut bien le dire, l'utilisation de pointeurs ne devrait être envisagée que de manière particulièrement exceptionnelle, et les pointeurs intelligents sont souvent de nature à apporter un minimum de sécurisation à leur utilisation.

    On parle justement des pointeurs intelligents dans cette discussion... peut être te convaincra-t-elle
    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

  3. #3
    Membre Expert
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Par défaut
    Merci pour cette réponse détaillée

    Pour la première question ca me rassure je ne suis pas fou ^^

    Et pour la deuxième, j'ai toujours utilisé les pointeurs car je suis à l'aise avec sauf au niveau de la libération de la mémoire parfois j'oublie et c'est chiant xD

    Avant je programmais en C avec des typedef (structures) et j'étais obligé d'utiliser les pointeurs pour que les attribus des "objets" soient modifiés dans tous mes sous programmes.

    En C++, j'ai gardé cette habitude sans me poser la question si c'était nécessaire. En fait quand je vais bouger un ennemie donc modifier ses attribus posX et posY, si j'utilise pas de pointeur, est ce que ca sera pris en compte dans tous les sous programmes qui utilise l'objet "ennemie" ?

    Sinon pour en revenir aux pointeurs intélligents, j'ai vu ca dans la FAQ et ca m'a pas emballer pour dire la vérité, car je dois apprendre une nouvelle notion et apparemment y'a de risques donc il faut faire attention.

    Mais je vois pas l'intéret de mettre des blocs try/catch partout pour récupérer les exeptions car si un new échoue par manque de mémoire (chose improbable sur nos pc actuels), le programme plante et puis c'est tout
    Je comprends pas où y'a une fuite de mémoire ? car quand un programme a planté et qu'il est fermé, normalement toutes les ressources sont libérés non ?

    Désolé si j'ai l'air ignorant mais je maitrise bien le C/C++ c'est juste que niveau mémoire, je m'en suis jamais préoccupé car je codais des petits trucs de 500 lignes mais sur un projet tel qu'un jeu, je ne peux pas "m'en foutre"
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Citation Envoyé par Aspic Voir le message
    Merci pour cette réponse détaillée

    Pour la première question ca me rassure je ne suis pas fou ^^

    Et pour la deuxième, j'ai toujours utilisé les pointeurs car je suis à l'aise avec sauf au niveau de la libération de la mémoire parfois j'oublie et c'est chiant xD

    Avant je programmais en C avec des typedef (structures) et j'étais obligé d'utiliser les pointeurs pour que les attribus des "objets" soient modifiés dans tous mes sous programmes.
    Oui, mais, si c'est pour programmer en C++ comme on programme en C, on perd tous les avantages que C++ peut apporter
    En C++, j'ai gardé cette habitude sans me poser la question si c'était nécessaire. En fait quand je vais bouger un ennemie donc modifier ses attribus posX et posY, si j'utilise pas de pointeur, est ce que ca sera pris en compte dans tous les sous programmes qui utilise l'objet "ennemie" ?
    La réponse tient en un mot: référence...

    Fais petit tour par la FAQ ou une recherche sur le forum pour comprendre, mais tu as, en plus, l'énorme avantage d'assurer l'existence de l'objet passé par référence
    Sinon pour en revenir aux pointeurs intélligents, j'ai vu ca dans la FAQ et ca m'a pas emballer pour dire la vérité, car je dois apprendre une nouvelle notion et apparemment y'a de risques donc il faut faire attention.
    Comme je le faisais remarquer dans ma première intervention à la discussion que je vient de citer, leur apprentissage représente un investissement qui sera très largement récupéré par la suite
    Mais je vois pas l'intéret de mettre des blocs try/catch partout pour récupérer les exeptions car si un new échoue par manque de mémoire (chose improbable sur nos pc actuels), le programme plante et puis c'est tout
    La gestion d'erreurs est un problème tout à fait différent qui, justement, est abordé depuis pas très longtemps dans cette discussion
    Je comprends pas où y'a une fuite de mémoire ? car quand un programme a planté et qu'il est fermé, normalement toutes les ressources sont libérés non ?
    Une fuite mémoire n'est pas *particulièrement* importante au moment où le programme plante, mais ca peut être la cause du plantage...

    Il faut te dire que ton application est rarement la seule application qui tourne sur le PC.

    Et le fait est qu'une fuite mémoire met en péril l'ensemble du système: si une application présente une fuite mémoire, cela peut porter préjudice à ta propre application, même si cette dernière n'en souffre absolument pas

    Désolé si j'ai l'air ignorant mais je maitrise bien le C/C++
    On passe son temps à militer pour que l'on ne fasse pas l'amalgame C et C++, et ce n'est pas un hazard...

    Si C++ revendique son héritage du C, il faut vraiment comprendre que ce sont deux langages totalement différents et que l'idéal est d'éviter à tout prix les possibilités du C lorsqu'il existe une possibilité identique propre au C++.
    c'est juste que niveau mémoire, je m'en suis jamais préoccupé car je codais des petits trucs de 500 lignes mais sur un projet tel qu'un jeu, je ne peux pas "m'en foutre"
    Effectivement.

    Et, justement, cela plaide, encore une fois, en faveur de l'utilisation des possibilités offertes par C++ chaque fois que possible.

    Tu t'éviteras de nombreux cheveux gris, quelle que soit la taille du projet
    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
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Par défaut
    OKi merci pour toute ces infos, j'essaye déjà de limiter le plus possible le C (genre pas de malloc, free ou de fonction pourris pour gérer les chaines de caractères (vive la classe string !)) mais parfois c'est inévitable

    Sinon juste une question, je viens de trouver une fuite de mémoire car je n'avais pas initialisé une variable (honte à moi ) mais le bloc try/catch ne l'a pas levé je comprends pas pourquoi...

    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
     
    try
    {
    int dir = 0;
    int imageCourante = -1; // exprès pour provoquer l'erreur
    sprite_courant = sprites[dir][imageCourante];
    }
    catch ( const std::out_of_range &tmp)
    {
        cout << "Erreur : débordement de mémoire." << tmp.what() << "\n";
    }
    catch (const std::exception &tmp)
    {                
        cout << "Erreur erreur ! (cause " << tmp.what() << ")" << endl;
    }
    catch (...)
    {
       cout << "erreur ";
    }
    Ca ne pase pas dans le catch... bizarre, j'ai essayé plein de catch différent dont std::exception, std::out_of_range mais ca ne passe pas...

    Une idée ?

    Encore merci pour tes explications
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Citation Envoyé par Aspic Voir le message
    OKi merci pour toute ces infos, j'essaye déjà de limiter le plus possible le C (genre pas de malloc, free ou de fonction pourris pour gérer les chaines de caractères (vive la classe string !)) mais parfois c'est inévitable

    Sinon juste une question, je viens de trouver une fuite de mémoire car je n'avais pas initialisé une variable (honte à moi ) mais le bloc try/catch ne l'a pas levé je comprends pas pourquoi...

    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
     
    try
    {
    int dir = 0;
    int imageCourante = -1; // exprès pour provoquer l'erreur
    sprite_courant = sprites[dir][imageCourante];
    }
    catch ( const std::out_of_range &tmp)
    {
        cout << "Erreur : débordement de mémoire." << tmp.what() << "\n";
    }
    catch (const std::exception &tmp)
    {                
        cout << "Erreur erreur ! (cause " << tmp.what() << ")" << endl;
    }
    catch (...)
    {
       cout << "erreur ";
    }
    Ca ne pase pas dans le catch... bizarre, j'ai essayé plein de catch différent dont std::exception, std::out_of_range mais ca ne passe pas...

    Une idée ?

    Encore merci pour tes explications
    C'est normal, un tableau C style ne connait absolument pas sa taille...

    l'exception out_of_range est essentiellement lancée par... les collections de la STL, et non par les tableaux C style (qui ignorent même que les exceptions existent)

    De plus, quand tu défini la valeur d'un entier (signé) à -1 pour forcer à l'erreur, tu ne force absolument rien:

    Je ne suis pas tout à fait sur de ce qui se passe, mais

    Soit tu accède, tout simplement, à l'adresse pointée par sprites[dir] -1, soit ton entier est considéré non pas comme un entier signé, mais comme un entier non signé.

    En effet, la représentation en mémoire d'un entier signé est strictement identique à celle d'un entier non signé, la seule différence résidant dans le fait qu'un bit (sur ... 32, typiquement ) sert à représenter le signe de la valeur.

    Les valeurs négatives sont, souvent représentée en ce qu'on appelle "complément à 2".

    Ainsi, si la valeur 1 est représentée, en hexadécimal, sous la forme de 0x00000001, la valeur -1 sera, souvent, représentée sous la forme de 0xFFFFFFFF.

    Or, sous sa forme non signée, la valeur 0xFFFFFFFF représente la valeur...4 294 967 295

    Et, comme une adresse mémoire n'est jamais qu'une valeur numérique, il est tout à fait possible d'additionner cette valeur à une adresse, même si, le dépassement de la valeur fait que... le résultat fera que l'on "recommencera" à un certain moment à compter à 0, ce qui reviendra sans doute (en fonction du nombre de valeurs disponibles pour représenter les adresse mémoire) à... soustraire un à l'adresse d'origine
    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

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 27/05/2006, 13h30
  2. Problème libération de mémoire?
    Par Bartuk dans le forum C
    Réponses: 7
    Dernier message: 28/12/2005, 17h20
  3. Libération de mémoire
    Par petitcoucou31 dans le forum Langage
    Réponses: 1
    Dernier message: 16/09/2005, 14h10
  4. [Debutant(e)]problème de libération de mémoire
    Par skywalker3 dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 10/02/2005, 17h38
  5. Réponses: 25
    Dernier message: 16/07/2003, 20h41

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