Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème fuite de mémoire QT

Sujet résolu
    18 juin 2018 à 11:09:17

    Bonjour à tous.

    J'ai un programme qui me permet de récupérer dans un fichier texte , les valeurs des pixels d'une caméra. Après les avoir récupéré , je met ma QImage dans un QPixmap puis dans un QLabel pour l'afficher dans mon layout. Ma fonction est appelé toutes les 200 ms afin d'avoir 5 fps. 

    Cependant , j'ai une fuite de mémoire , la mémoire augmente de plus en plus. En cherchant un peu , j'ai vu qu'un QPixmap était un objet assez spéciale et qu'il était lié au QPixmapCache. J'ai donc fait un petit : QPixmapCache::clear() à la fin de ma fonction mais rien n'y fait. 

    void Camera::AffichageImage()
    
    {
    
        label_img2  = new QLabel;
    
    
    
    
    
        QImage image;
        image=getImage();
    
        QPixmap pixmap;
        pixmap = QPixmap::fromImage(image);
    
    
    
    
        label_img2->setPixmap(pixmap);
    
        layout->addWidget(label_img2,0,6,5,5);
    
    
        bouton = new QPushButton("Stop");
        bouton->setFont(QFont("Courrier", 14));
        bouton->setCursor(Qt::PointingHandCursor);
        bouton->setGeometry(1,100,1,100);
    
        layout->addWidget(bouton,5,8);
    
        QObject::connect(bouton, SIGNAL(clicked()), this, SLOT(AffichageBouton()));
        Camera::adjustSize();
    
    
        pixmap.isNull();
        QPixmapCache::clear();
    
            QTimer *timer = new QTimer(this);
                connect(timer, SIGNAL(timeout()), this, SLOT(AffichageImage()));
                timer->start(2000);//*1000 pour convertir en seconde(par Default ici c'est en millisecondes .
    
    
    }

    -
    Edité par BenjaminTheytaz1 18 juin 2018 à 11:10:23

    • Partager sur Facebook
    • Partager sur Twitter
      18 juin 2018 à 11:39:13

      Salut,

      J'ai pas regarder en détail mais on voit de suite qu'il y a 3 new sans delete dans ta fonction (un Label, un Bouton et un Timer) (d'ailleur, ce serait bien que le label et le bouton aie un parent) et que chaque nouveau Timer va rappeler la fonction toute les 2s instanciant à nouveau ceux-ci (et donc des timers qui vont rappeler l'instanciation, c'est exponentiel)

      Mais pourquoi est-ce que cette fonction s'occupe de l'UI ? Je pense qu'elle devrait s'occuper uniquement de l'image

      • Partager sur Facebook
      • Partager sur Twitter
      Dream on, Dream on, Dream until your dream comes true
        18 juin 2018 à 15:01:44

        C'était ça ;)

        J'avais cherché un peu avec le message d'erreur et j'était tombé que sur des post parlant de la non destruction du QPixmap. 

        Du coup j'ai aussi crée une nouvelle fonction pour l'UI de cette fenêtre (bouton + Label) qui appelle cette fonction , c'est un peu plus propre. 

        Pourquoi faut t'il assigné un parent a mon label et mon bouton ? Si rien n'est indiqué , il n'est pas assigné à la classe de ma fonction ?
        • Partager sur Facebook
        • Partager sur Twitter
          18 juin 2018 à 15:49:46

          BenjaminTheytaz1 a écrit:

          Pourquoi faut t'il assigné un parent a mon label et mon bouton ? Si rien n'est indiqué , il n'est pas assigné à la classe de ma fonction ?


          Non, si tu regardes la doc ou un fichier d'entête, l'argument par défaut est nullptr, donc personne n'est responsable de sa destruction, tu dois le gérer manuellement quelque part

          BenjaminTheytaz1 a écrit:

          Du coup j'ai aussi crée une nouvelle fonction pour l'UI de cette fenêtre (bouton + Label) qui appelle cette fonction , c'est un peu plus propre.


          Gère le timer ailleurs aussi, tu peux l'instancier et le connecter dans le constructeur par exemple, et le démarrer uniquement à l'appel de la fonction

          -
          Edité par romantik 18 juin 2018 à 15:53:40

          • Partager sur Facebook
          • Partager sur Twitter
          Dream on, Dream on, Dream until your dream comes true
            18 juin 2018 à 15:58:14

            Salut,

            romantik a écrit:

            Salut,

            J'ai pas regarder en détail mais on voit de suite qu'il y a 3 new sans delete dans ta fonction (un Label, un Bouton et un Timer) (d'ailleur, ce serait bien que le label et le bouton aie un parent) et que chaque nouveau Timer va rappeler la fonction toute les 2s instanciant à nouveau ceux-ci (et donc des timers qui vont rappeler l'instanciation, c'est exponentiel)

            Mais pourquoi est-ce que cette fonction s'occupe de l'UI ? Je pense qu'elle devrait s'occuper uniquement de l'image


            Oui, mais, Hé!! Ho!!! on est en plein dans le système parent/enfants de Qt là...

            Comme image va dans pixmap, que pixmap va dans le label et que le label va dans le layout de la caméra, le système parent / enfants de Qt devrait faire le reste à partir du moment où la caméra sera détruite correctement (soit grâce au système parent/enfants si elle dépend "d'autre chose" soit au travers des différentes possibilités qui nous sont données pour la détruire automatiquement ou non).

            Et il en va de même du QTimer qui entre lui aussi dans le système parent/enfants de la caméra ;)

            Par contre, tous ces éléments ne devraient pas être créé dans une fonction comme "AffichageImage" parce que cela signifie qu'il seront recréés de manière systématique à chaque appel de la fonction, et que le bouton créé lors de l'appel N° X va prendre la place de celui créé lors de l'appel X-1 à cette fonction, ce qui provoquera une fuite mémoire.

            Sans oublier que l'on créera à chaque fois un timer supplémentaire ... à usage unique :p

            Le code que l'on voit là devrait prendre place dans... le constructeur de camera.  timer devrait donc être connu comme une donnée membre de camera, et il "suffirait" d'appeler timer->start() dans la fonction AffichageImage pour que les choses se passent correctement ;)

            • Partager sur Facebook
            • Partager sur Twitter
            Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
              18 juin 2018 à 16:09:54

              Exact, j'avais oublié que le layout prenais automatiquement la responsabilité du widget ... Dammit QtDesigner, tu me ramolis !

              koala01 a écrit:

              Sans oublier que l'on créera à chaque fois un timer supplémentaire ... à usage unique :p

              Mais le QTimer n'est pas en singleShot par défaut, pourquoi tu dis que c'est un usage unique ?

              Quant au reste, oui ça se détruisait normalement, mais j'ai répondu à ce qui inquiétais l'auteur, c'est à dire qu'il voyait sa consommation mémoire gonfler, ce qui n'est pas la définition de la fuite mémoire certes x)

              • Partager sur Facebook
              • Partager sur Twitter
              Dream on, Dream on, Dream until your dream comes true
                18 juin 2018 à 16:28:35

                romantik a écrit:

                Mais le QTimer n'est pas en singleShot par défaut, pourquoi tu dis que c'est un usage unique ?

                Parce que chaque appel à AffichageImage crée un nouveau timer qui sera utilisé...

                Le timer créé (et qui ne sera détruit que lors de la destruction de la caméra) ne sera donc utilisé que... jusqu'à l'appel suivant à AffichageImage  :p

                • Partager sur Facebook
                • Partager sur Twitter
                Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                  18 juin 2018 à 17:27:46

                  Excuse moi je ne comprends toujours pas

                  chaque appel à AffichageImage crée un nouveau timer, mais les précédents sont toujours actifs et déclenchent des timeouts qui vont appeler AffichageImage

                  donc après un premier appel :
                  t=0s : 1 timer
                  t=2s : le timer déclenche 1 appel à AffichageImage -> 1 ancien + 1 nouveau = 2 timers
                  t=4s : les timers déclenchent 2 appels à AffichageImage -> 2 anciens + 2 nouveaux = 4 timers
                  t=6s : les timers déclenchent 4 appels à AffichageImage -> 4 anciens + 4 nouveaux = 8 timers
                  ...
                  (en négligeant les temps d'exécutions qui vont décaler les appels)

                  On utilise tout le temps tout les timers et pas que d'un appel sur l'autre
                  C'est pour ça que j'avais pensé que sa consommation mémoire était exponentielle

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Dream on, Dream on, Dream until your dream comes true
                    18 juin 2018 à 22:05:05

                    Oui, au temps pour moi...

                    Mais c'est donc encore pire que ce que je croyais :p

                    • Partager sur Facebook
                    • Partager sur Twitter
                    Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                      19 juin 2018 à 14:32:26

                      Merci à tous pour vos réponses :) j'en apprend un peut plus sur QT. Je fait tous en autodidacte donc parfois je tombe sur des "petits problème" comme celui-ci qui sont facile à résoudre. Je le saurais pour plus tard ;)
                      • Partager sur Facebook
                      • Partager sur Twitter

                      Problème fuite de mémoire QT

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                      • Editeur
                      • Markdown