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 :

[Qt Charts] Fuite de mémoire avec QChartView


Sujet :

Qt

  1. #1
    Membre régulier
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Points : 97
    Points
    97
    Par défaut [Qt Charts] Fuite de mémoire avec QChartView
    Bonjour tout le monde,

    J'ouvre ce thread car je n'arrive pas à trouver de solution à mon problème.

    Actuellement, j'écris un programme qui génère de façon régulière un vecteur de points (classe signal dans l'exemple ci dessous).

    Ces points, je les représente dans un qchartview. Le problème est que je n'arrive pas à vider mon qchartview avant de rajouter mes nouveaux points ce qui provoque des fuites mémoires.

    Voici une partie du code.


    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
    void Signal::Draw(QChartView *a) 
    {
    	QChart *TheChart = new QChart;
    	QLineSeries *TheQLineSeries = new QLineSeries;	
    	int i;
     
     
    	for ( i= 0; i < mSignal.length(); i++)
    	{
    		TheQLineSeries->append(i, mSignal.at(i));
    	}
     
    	TheQLineSeries->setUseOpenGL(USEOPENGL);
    	TheChart->addSeries(TheQLineSeries);
    	TheChart->createDefaultAxes();	
    	a->chart()->removeAllSeries(); 
    	a->setChart(TheChart);
     
    }

    Avez vous une idée?

  2. #2
    Membre éclairé Avatar de AuraHxC
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    652
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

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

    Informations forums :
    Inscription : Mai 2006
    Messages : 652
    Points : 683
    Points
    683
    Par défaut
    Je me lance...

    Quand je lis la documentation, je lis ceci : "Sets the current chart to chart. Ownership of the new chart is passed to chartview and ownership of the previous chart is released. To avoid memory leaks users need to make sure the previous chart is deleted."

    Donc à priori, ton QChartView devient le maître... donc j'imagine qu'en détruisant ton QChartView cela va détruire le QChart, puis tu reconstruis un QChartView. Ou alors autre idée mais je sais pas si cela va passer ou même si cela est vraiment propre... c'est de récupérer le pointeur à l'aide de la méthode QChart *QChartView::chart() const et de faire par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    QChart *qc = a->chart(); // Récupération de l'ancien QChart
    a->setChart(TheChart); // Ajout du nouveau QChart
    delete qc; // Suppression de l'ancien QChart

  3. #3
    Membre régulier
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Points : 97
    Points
    97
    Par défaut
    Hey AuraHxC!

    Merci pour ta réponse.

    Hé bien figure toi que j'avais essayé ta solution (bien que je ne l'ai pas évoquée ici).


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    QChart *qc = a->chart(); // Récupération de l'ancien QChart
    a->setChart(TheChart); // Ajout du nouveau QChart
    if(a->Charts!=nullptr){
    delete qc; // Suppression de l'ancien QChar
    }
    J'ai une exception qui est lancée. Je ne suis pas au bureau là. Je développerai ça dès que j'y passerai

  4. #4
    Membre éclairé Avatar de AuraHxC
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    652
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

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

    Informations forums :
    Inscription : Mai 2006
    Messages : 652
    Points : 683
    Points
    683
    Par défaut
    Effectivement c'est ce que je proposais... sauf que j'imagine que ça doit être une faute de frappe car ça doit être plus if (a->chart() != nullptr)
    Tu pourras nous dire l'exception que tu obtiens quand tu pourras histoire d'avoir toutes les cartes en main

  5. #5
    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 AuraHxC Voir le message
    Je me lance...
    Ou alors autre idée mais je sais pas si cela va passer ou même si cela est vraiment propre... c'est de récupérer le pointeur à l'aide de la méthode QChart *QChartView::chart() const et de faire par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    QChart *qc = a->chart(); // Récupération de l'ancien QChart
    a->setChart(TheChart); // Ajout du nouveau QChart
    delete qc; // Suppression de l'ancien QChart
    Hum, ca, ca ne me semble pas être une bonne idée : QChartView::char() est marquée comme étant une fonction constante, c'est à dire que l'utilisation du (pointeur vers) QChart que l'on récupère ne devrait pas permettre la modification de l'état de la vue. Or, la libération de ce pointeur est -- typiquement -- une action qui va modifier l'état de la vue : dans le meilleur des cas (si on a veillé à fournir un autre QChart), il faudra passer par la mise à jour de la vue, dans le pire, (si on ne veille pas à lui fournir un autre QChart), ca la mettra dans un état inconsistant (comment veux tu que la QChartView puisse afficher un QChart si elle n'en a pas ou, pire encore, si le pointeur interne vers celui-ci renvoie à une adresse invalide ).

    Du coup, si l'idée est d'utiliser setChart, la logique voudrais que l'on s'assure que tout soit fait "dans les règles du lard" (pardon, de l'art) en s'assurant qu'une logique proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /*soit m_chart est un pointeur sur QChart 
     * et m_view est un pointeur sur QChartView
     */
     
    delete m_chart;            // 1- on détruit l'ancien chart
    m_chart = new QChart;      // 2- on crée le nouveau
    /* on remplit m_chart avec les données qui nous intéressent */
    m_view->setChart(m_chart); // 3- on met le QChart à jour au niveau de la vue 
    m_view->repaint() ;        // 4- on force la mise à jour de la vue
    De plus, la classe QChart propose la fonction releaseAllSeries qui, si j'ai bien compris, a pour résultat de vider le contenu du QChart. Plutôt que de détruire le QChart pour en recréer un (ce qui serait quand même moche, si on peut faire autrement), pourquoi ne pas travailler "à peu près" de la même manière que ce que je viens d'expliquer, mais en se contentant de ... vider le QChart avant de le re-remplire

    Cela donnerait quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /*soit m_chart est un pointeur sur QChart 
     * et m_view est un pointeur sur QChartView
     */
    m_chart->releaseAllSeries();  // 1- on "vide" le QChart de son contenu
    /* on remplit m_chart avec les données qui nous intéressent */
    /* comme la vue est toujours reliée à m_chart, il n'y a rien à faire pour changer
     * cet état de fait qui nous convient très bien
     */ 
    m_view->repaint() ;           // 2- "il faut juste" indiquer à la vue qu'elle doit être mise à jour
    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 éclairé Avatar de AuraHxC
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    652
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

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

    Informations forums :
    Inscription : Mai 2006
    Messages : 652
    Points : 683
    Points
    683
    Par défaut
    On est complètement d'accord que ma proposition était très sale !!! Je voyais juste pas d'autre solution au moment où j'ai répondu... j'aurais dû un peu mieux regarder et pas trop me précipiter car à priori j'avais pas bien regardé la méthode releaseAllSeries() car effectivement c'est, je pense et comme tu le dis, la clé du problème initial.

  7. #7
    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
    Ceci dit, j'ai -- moi aussi -- fait une erreur idiote, car, a priori :
    1. La mise à jour d'un enfant (m_chart, dans le code que je présentais) entraine automatiquement la mise à jour du parent (m_view dans mon code)
    2. l'ajout d'un élément dans m_chart devrait forcément le marquer comme "devant être mis à jour", si bien qu'il serait automatiquement mis à jour lors de la boucle suivate

    Si bien que, sauf erreur de ma part (tout est toujours possible, n'est-ce pas ), nous devrions pouvoir nous contenter d'appeler releaseAllSeries() avant de remplir à nouveau notre QChart, et tout le reste devrait se faire de manière automatique
    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

  8. #8
    Membre régulier
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Avril 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Avril 2014
    Messages : 105
    Points : 97
    Points
    97
    Par défaut
    Bonjour Messieurs et merci pour vos pistes.

    Tout d’abord, je ne sais pas si c'est une erreur de ma part, mais je n'arrive pas à trouver la méthode releaseAllSeries qui ne semble pas exister dans la classe QCharts. Est ce que vous êtes sur que vous ne parlez pas de la méthode removeAllseries que j'emploie? En effet celle-ci semble avoir la même définition que celle que vous avez exposée :

    void QChart::removeAllSeries()
    Removes and deletes all series objects that have been added to the chart.
    Du coup, en utilisant removeAllseries, j'ai ce problème de fuite mémoire.

    Du coup j'ai creusé les autres méthodes.

    Celle ci fonctionne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    QChart *qc = a->chart(); // Récupération de l'ancien QChart
    a->setChart(TheChart); // Ajout du nouveau QChart
    delete qc; // Suppression de l'ancien QChart

    En revanche celle ci ne fonctionne pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    QChart *qc = a->chart(); // Récupération de l'ancien QChart
    delete qc; // Suppression de l'ancien QChart
    a->setChart(TheChart); // Ajout du nouveau QChart
    Bref, même si ça fonctionne, je ne suis pas du tout convaincu. Je ne comprends pas où est la partie Removes and deletes all series objects that have been added to the chart

Discussions similaires

  1. Fuite de mémoire avec GUI Swing
    Par pouvoir triforce dans le forum AWT/Swing
    Réponses: 6
    Dernier message: 17/06/2011, 00h26
  2. Fuite de mémoire avec VBO ?
    Par poliok dans le forum OpenGL
    Réponses: 7
    Dernier message: 08/11/2010, 16h09
  3. Fuites de mémoire avec cvLoadImage et cvCvtColor
    Par Fabounch dans le forum OpenCV
    Réponses: 2
    Dernier message: 03/03/2010, 11h45
  4. Problème de fuite de mémoire avec GTK+
    Par gwenhael dans le forum GTK+
    Réponses: 15
    Dernier message: 03/01/2008, 16h22
  5. Fuite mémoire avec valgrind
    Par franchouze dans le forum C++
    Réponses: 3
    Dernier message: 05/06/2006, 16h47

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