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 :

probleme avec le destructeur


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    Février 2007
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2007
    Messages : 107
    Par défaut probleme avec le destructeur
    j'arrive pas trop bien a comprendre les destructeur en c++
    et come jai une application qui bouffe enormemant de memoire je veut liberer ce que j'ai a chaque boucle

    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
     
    void Matrice3D::CalculMatrice(){
    	float pas = 2./DIM;
     
    	Line3 *lignex;
            for (int k=0; k<DIM;k++)
    		for (int i=0; i<DIM;i++)
    			for (int j=0; j<DIM;j++)
    			{
     
    			lignex = new Line3(*new Vector3(k*pas,i*pas, j*pas),
    				*new Vector3(k*pas,i*pas, j*pas));
     
     
    				// jai pas encore fait le code ici
     
     
    			}
    		delete lignex;
     
     
    }
    ça me fait un segmentation fault

    je comprends pas trop et de l'autre coté j'ai
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Line3::~Line3()
    	{
    	//the self destruction
     
    	delete this;
    	};
    voila si quelq'un peut me dire koi faire

    merci

  2. #2
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Par défaut
    Hello,

    Plusieurs remarques.

    1] D'abord sur le fonctionnement des destructeurs. Lorsque tu écris :
    Avec p de type A*, le compilateur génère le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    p->~A();
    free(p);
    Autrement dit appel du destructeur puis libération de la mémoire. Ton destructeur pose donc problème, en appelant delete *this, en théorie tu crées une boucle infinie d'appel du destructeur et de libération mémoire. En pratique, vu que tu tentes de libérer deux fois la même zone mémoire, tu plantes le programme.

    2] Ta boucle leak. Dans ton cas, si tu veux libérer la mémoire, il faut le faire dans le scope où elle est allouée. Dans ton code, tu alloues DIM-1 Line3 pour ta troisième boucle, mais n'en libère qu'une après cette boucle. Un code sans leak :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    for(int i = k = 0; k < DIM; k++)
        for(int i = 0; i < DIM; i++)
            for(int j = 0; j < DIM; j++)
            {
                lignex = new Line3(....);
                //...
                delete lignex;
            }
    3] L'allocation/libération dynamique est plus coûteuse qu'une allocation/désalocation sur la pile. Ddans la mesure où tu n'as pas besoin de ta variable lignex en dehors de ta troisième boucle, tu devrais plutôt opter pour le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    for(int i = k = 0; k < DIM; k++)
        for(int i = 0; i < DIM; i++)
            for(int j = 0; j < DIM; j++)
            {
                Line3 lignex(....);
                //...
            }
    Et là plus de soucis de mémoire à libérer.

    4] Apparemment ton destructeur de Line3 ne désalloue rien, alors que tu passes à son constructeur des paramètres alloués dynamiquement ; comme tu ne gardes aucun pointeur sur ces éléments tu n'as aucun moyen de les désallouer ensuite, et ça leak. Il faut donc que tu passes directement des pointeurs à ton constructeur Line3, et le destructeur se chargera des les libérer (ou mieux tu utilises des auto_ptr), ou que tu passes des variables automatiques et ton constructeur en fait une copie.

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

    Informations professionnelles :
    Activité : aucun

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

    Il y a vraisemblablement une mauvaise compréhension de ta part sur le travail effectué par delete et par le destructeur.

    delete va travailler en deux temps:
    1. invoquer le destructeur de l'objet au sujet duquel il est appelé (obj->~MaClasse(); )
    2. libérer la mémoire qui a été allouée dynamiquement pour cet objet (free(obj); ).


    Le but du destructeur est, prour sa part, de "faire le ménage" non pas de l'objet, mais... des membres qui le composent.

    Cela peut aller jusqu'à invoquer delete sur les... membres de l'objet pour lesquels de la mémoire a été allouée dynamiquement.

    En outre, this est un pointeur sur... l'objet lui-même, ce qui permet d'avoir un "point d'entrée" pour accéder aux différents membres et méthodes de l'objet lui-même, une fois que l'on se trouve dans une méthode de l'objet.

    C'est la raison pour laquelle, il ne faut - à de très rares exceptions près (je ne connait que le pattern "singleton" qui justifie de le faire) - ne jamais invoquer delete sur le pointeur this, et, en tout état de cause, jamais dans le destructeur.

    En effet, si l'on décide même de ne pas prendre le coté récursif d'un destructeur proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    MaClass::~MaClass()
    {
        delete this;
        /* ce qui revient à peut de chose près à
         * this->~MaClass();
         * free(this);
    }
    lorsque que tu invoque delete sur un objet sous la forme de
    delete obj;
    cela revient à peut de chose près à écrire un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    obj->~MaClass();
    free(obj);
    et, comme tu demanderais dans ~MaClass de ... libérer la mémoire allouée à this, pointant pour l'occasion sur obj, lorsque tu arrive à free(obj), il se fait que la mémoire qui lui était allouée a ... déjà été libérée.

    Au final, si l'on peut considérer qu'aucune méthode de ligne n'invoque un new d'allocation dynamique sur un des membres de la classe Line3, supprime simplement le delete du destructeur de Line3et laisse le destructeur vide.

    Si, par contre, certains membres de Line3 sont gérés sous la forme de pointeurs pour lesquels une gestion dynamique de la mémoire est utilisée, contente toi d'invoquer delete (ou delete[], selon le cas) pour ... les membres qui sont dans le cas
    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 chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Par défaut
    Citation Envoyé par koala01 Voir le message
    C'est la raison pour laquelle, il ne faut - à de très rares exceptions près (je ne connait que le pattern "singleton" qui justifie de le faire) - ne jamais invoquer delete sur le pointeur this, et, en tout état de cause, jamais dans le destructeur.
    Je ne vois pas en quelle implémentation du pattern singleton justifie l'emploi de delete this, a priori l'allocation et la libération d'un singleton se font via des fonctions statiques qui allouent/détruisent un pointeur statique. A quel type d'implémentation fais tu référence ?

    J'aurais plutôt vu le cas d'un programme multithread, quand un thread est le seul à savoir quand il doit mourrir.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 633
    Par défaut
    En fait, j'étais un peu mal réveillé au moment d'écrire le message, et je me suis mal exprimé...

    Ce n'est bien évidemment pas sur this qu'il faut invoquer delete, mais sur l'instance statique du singleton

    D'aucuns estiment d'ailleurs avec raison qu'il n'y a normalement pas lieu de permettre à l'utilisateur de permettre de libérer cette ressource pour des raisons plus que valables
    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

  6. #6
    Membre confirmé
    Profil pro
    Étudiant
    Inscrit en
    Février 2007
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2007
    Messages : 107
    Par défaut
    Ok merci
    j'ai mieux compris maintenant

    encore merci

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

Discussions similaires

  1. Probleme avec la copie des surfaces
    Par Black_Daimond dans le forum DirectX
    Réponses: 3
    Dernier message: 09/01/2003, 10h33
  2. Problèmes avec le filtrage des ip
    Par berry dans le forum Réseau
    Réponses: 9
    Dernier message: 30/12/2002, 07h51
  3. probleme avec la touche F10
    Par b.grellee dans le forum Langage
    Réponses: 2
    Dernier message: 15/09/2002, 22h04
  4. Probleme avec fseek
    Par Bjorn dans le forum C
    Réponses: 5
    Dernier message: 04/08/2002, 07h17
  5. [Kylix] probleme avec un imagelist
    Par NicoLinux dans le forum EDI
    Réponses: 4
    Dernier message: 08/06/2002, 23h06

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