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

Qt Discussion :

Gestion de la mémoire par Qt : fuites possibles ?


Sujet :

Qt

  1. #1
    Membre habitué
    Homme Profil pro
    Doctorant en Astrophysique
    Inscrit en
    Mars 2009
    Messages
    312
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Astrophysique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2009
    Messages : 312
    Points : 176
    Points
    176
    Par défaut Gestion de la mémoire par Qt : fuites possibles ?
    Bonjour .


    Je code en ce moment un petit programme avec Qt 4.6 (sous Windows 7 x64, Codeblocks et mingw gcc 4.5.0) et j'ai de multiple questions pour tenter d'éclaircir ma vision quant à la gestion de la mémoire par Qt.


    Tout d'abord voici en gros mon programme de test :
    J'ai une QMainWindow Fenetre1 très simple avec un widget central (vide pour le moment) et une menuBar. Dans cette menuBar, un clic sur l'un des menus doit ouvrir une nouvelle fenêtre Fenetre2 (type boîte de dialogue, mais éditée par moi et héritant directement d'un QWidget). Cette Fenetre2 regroupe plusieurs boutons ainsi qu'une animation .mng (QMovie) qui prend pas mal de place en mémoire. Je veux donc que quand l'on ferme cette Fenetre2, tout ce qui était en mémoire associé à celle-ci soit correctement effacé.


    Concernant l'allocation en mémoire voici les différentes techniques utilisées pour les déclaration de variables (et j'aimerai des précisions là dessus) :


    Technique 1 : Variable locale dans fonction membre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void MaClasse::MaFonction()
    {
        QString maVariable;
        maVariable="Bonjour";
    }
    Question 1 : pouvez vous me confirmer qu'une fois que MaFonction a été exécutée, maVariable est effacée ?


    Technique 2 : Variable locale dans fonction membre par pointeur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void MaClasse::MaFonction()
    {
        QPushButton *monBouton=new QPushButton("Cliquez!",this);
    }
    Question 2 : là normalement, à chaque fois que la fonction est exécutée, un nouveau bouton est créé. Ils sont tous détruits quand MaClasse est détruite. C'est ça ?
    Question 3 : par contre si l'on ne met pas le parent "this", et que l'on met 0 à la place que se passe-t-il ? Chaque nouvel appel devrait créer un nouveau bouton mais quand MaClasse sera détruite, les boutons ne le seront pas...


    Technique 3 : Variable membre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        private:
            QPushButton monBouton;
    ------------------------------------------------------------
    void MaClasse::MaFonction()
    {
        monBouton.setText(Cliquez!);
    }
    Question 4 : en principe là, monBouton est créé avec la classe et est détruit avec elle. Donc à priori pas trop de problème de mémoire. J'ai bon ?



    Technique 4 : Variable membre par pointeur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        private:
            QPushButton *monBouton;
    ------------------------------------------------------------
    void MaClasse::MaFonction()
    {
        monBouton=new QPushButton("Cliquez!",this);
    }
    Question 5 : Alors là, j'ai un peu plus de mal. En principe MaFonction ne devra être appelée qu'une seule fois, et dans le constructeur. Que se passe-t-il si jamais MaFonction est exécutée plusieurs fois ? (donc plusieurs new pour le même objet)
    Question 6 : En principe, si le parent est défini comme "this", le bouton sera détruit lorsque MaClasse sera détruite, c'est ça ?
    Question 7 : Et si le parent est défini comme 0 au lieu de this, que se passera-t-il lors de la destruction de la classe ?

    Question 8 (plus générale) : Dans les codes Qt, en général, les objets dérivés de Q_OBJECT sont gérés avec les techniques 2 et 4, tandis que les autres (comme les QPixmap par exemple) avec les techniques 1 et 3. Or si je vois l'intérêt de la technique 2 pour construire plusieurs objets avec une même fonction, j'ai beaucoup plus de mal avec la technique 4 puisqu'en général les objets sont initialisés dans le constructeur (du coup la technique 3 serait plus sûre non ?).


    Mon problème de mémoire :

    Actuellement, ma Fenetre2 est déclarée avec la Technique 2 dans l'un des slot associé à ma menuBar de la Fenetre1. Sans mesure particulière sur la Fenetre2, à chaque fois qu'on la ferme (avec un slot close()), l'animation reste en mémoire, et un nouveau clic dans la menuBar créé une nouvelle fenêtre avec une nouvelle animation (problème de mémoire donc...).
    Si, dans le constructeur de la Fenetre2, je met un setAttribute(Qt::WA_DeleteOnClose) ça va déjà beaucoup mieux mais j'ai toujours un petit doute. Les mesures de mémoire application avec le gestionnaire des tâches de Windows (je n'ai pas d'autre moyen ) donne en effet (je lance et je ferme 5 fois la Fenetre2) :
    Début = 0 K
    Lancement application = 3180 K
    Déroulement des menus de la menuBar = 5116 K

    Lancement de la Fenetre2 - 1 = 79480 K
    Fermeture de la Fenetre2 - 1 = 7136 K

    Lancement de la Fenetre2 - 2 = 79452 K
    Fermeture de la Fenetre2 - 2 = 7640 K

    Lancement de la Fenetre2 - 3 = 79424 K
    Fermeture de la Fenetre2 - 3 = 7864 K

    Lancement de la Fenetre2 - 4 = 79796 K
    Fermeture de la Fenetre2 - 4 = 7540 K

    Lancement de la Fenetre2 - 5 = 79292 K
    Fermeture de la Fenetre2 - 5 = 7648 K
    ...
    Question 9 : Pourquoi à chaque lancement/fermeture de la Fenetre2, les valeurs ne sont jamais les mêmes ?

    Question 10 : Pourquoi à la fermeture la Fenetre2, on ne revient pas à 5116 K (Déroulement des menus de la menuBar) ?


    Merci mille fois à ceux qui prendront le temps de me lire et trouveront le temps de me répondre

    Merci.

  2. #2
    Membre habitué
    Homme Profil pro
    Doctorant en Astrophysique
    Inscrit en
    Mars 2009
    Messages
    312
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Astrophysique
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2009
    Messages : 312
    Points : 176
    Points
    176
    Par défaut
    Dans la doc de Qt, il est marqué, pour la fonction setLayout :
    "The QWidget will take ownership of layout."
    Ce qui, si je ne me trompe pas, signifie qu'au moment où setLayout est appelé, le QWidget devient le parent de layout, ce qui résout les problème d'allocation dynamique...

  3. #3
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 617
    Points
    15 617
    Par défaut
    Bonjour Kaluza

    En fait, beaucoup de questions concernent C++ plutôt que Qt.

    1. oui : variable locale déclarée dans un bloc, détruite à la sortie
    2. oui : le pointeur est détruit à la sortie de la fonction mais l'objet pointé non. Destruction par le système de parent-enfant de QObject
    3. les boutons ne seront pas détruit. Pour t'en convaincre, il suffit d'ajouter un monBouton->show() : chaque bouton sera affiché et ne seront pas détruits quand la fenêtre parent sera détruit
    4. FAQ : Allouer sur le tas ou sur la pile des QObject et dérivés ? en gros, il faut utiliser un pointeur. Voir aussi http://qt.developpez.com/faq/?page=Q...qobject-membre et http://www.developpez.net/forums/d97...ssion-qobject/
    5, 6 et 7. pareil que les questions 2 et 3, sauf que tu conserves un pointeur vers le dernier élément créé
    8. tout dépend de ce que tu veux faire... Dans le constructeur (qui est appelé une seule fois), tu crées qu'une seule fois tes objets. Mais tu peux souhaiter créer tes objets plusieurs fois (par exemple ouvrir un dialogue lors d'un clic sur un bouton)
    Remarque : "les objets dérivés de Q_OBJECT", Q_OBJECT est une macro (indispensable pour la gestion interne des objets), pas un objet. Les objets dérivent de QObject
    9 et 10. tu ne peux pas mesurer la consommation mémoire avec le gestionnaire de windows, ça n'a aucune valeur (il est évident qu'une fenêtre ne prend pas 74 Mo en mémoire). Il faut utiliser par exemple valgrind (sous linux, je connais pas un équivalent sous windows)
    De toute façon, une "vraie" fuite mémoire, la consommation augmenterait à chaque création et ferait plusieurs Go très rapidement, ce qui n'est pas le cas ici.
    11. non, en fait les fonctions addWidget et setLayout appellent la fonction setParent, ce qui a le même effet que de mettre un parent dans le constructeur

Discussions similaires

  1. Réponses: 3
    Dernier message: 09/05/2012, 09h21
  2. Gestion de la mémoire par Qt
    Par Kaluza dans le forum Qt
    Réponses: 16
    Dernier message: 31/08/2011, 15h48
  3. Gestion de la mémoire par la VM
    Par sloshy dans le forum Général Python
    Réponses: 3
    Dernier message: 13/09/2009, 03h14
  4. Gestion de la mémoire par jonas
    Par DevServlet dans le forum JOnAS
    Réponses: 2
    Dernier message: 13/01/2009, 18h01
  5. Réponses: 15
    Dernier message: 14/11/2007, 11h54

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