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 :

Destructeurs et valgrind


Sujet :

Qt

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 64
    Points : 40
    Points
    40
    Par défaut Destructeurs et valgrind
    Bonjour,

    Mon objectif est d'éviter les fuites mémoires. Avec valgrind si je ne mets pas de "delete testsOpengl;" dans le destructeur ~TestsRender() j'obtiens une fuite mémoire. Par contre si je mets un "delete testsOpengl;" dans le destructeur j'ai pas de fuite mémoire mais par contre valgrind me dit ceci :
    "pure virtual method called
    terminate called without an active exception
    "

    Je crois que ça vient du fait qu'il repasse plusieurs fois sur le destructeur de testsOpengl.
    Avec le debuger j'ai relevé l'ordre de destruction, et ça me donne ceci dans l'ordre : ~TestsOpengl() ---> ~Render() ---> ~TestsOpengl() ---> ~Tests() ---> ~TestsRender()

    J'aimerais bien sortir proprement de mon programme, merci d'avace voici le code sans les headers :

    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
     
    #include "tests.h"
    #include "rendering/render.h"
    int main(int argc, char *argv[])
    {
     
        QApplication Application(argc, argv);
        // pour libérer la mémoire après la fermeture de la dernière fenêtre
        QApplication::setQuitOnLastWindowClosed(false);
     
    #ifdef TESTS
     
        Tests tests;
        tests.run_tests();
     
    #endif //TESTS
     
        Application.exec();
        return 0;
    }
    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
     
    #include "tests.h"
    Tests::Tests() {
    }
     
    Tests::~Tests() {
            delete testsRender;
    }
     
    void Tests::run_tests() {
     
        // Instanciation des classes pour lancer les tests
        testsRender = new rendering::TestsRender();
     
        std::vector<QObject*>::iterator iSuite;
        for (iSuite = QTestSuite::m_suites.begin(); iSuite != QTestSuite::m_suites.end(); ++iSuite)
        {
            QTest::qExec(*iSuite);
        }
    }
    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
     
    #include "testsRender.h"
     
    namespace rendering {
     
        TestsRender::TestsRender() {
            testsOpengl = new TestsOpengl(24, 1000);
            testsOpengl->setGeometry(200,200,400,400);
            testsOpengl->show();
        }
     
        TestsRender::~TestsRender() {
            delete testsOpengl;
            testsOpengl = nullptr;
        }
    }
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    #include "testsOpengl.h"
     
    namespace rendering {
     
    TestsOpengl::TestsOpengl(const quint16 &framesPerSecond, const quint16 &interval_time) : Render(framesPerSecond, interval_time) {
    }
     
    TestsOpengl::~TestsOpengl() {
    }
     
    void TestsOpengl::paintGL()
    {
     
        // nettoie les buffers
        // GL_COLOR_BUFFER_BIT : Indique les buffers courrants actifs pour une écriture des couleurs
        // GL_DEPTH_BUFFER_BIT : Nettoie les Z-buffers (pour éviter la supperposition de couleurs arrière sur des couleurs avant)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        // charge la matrice Identité
        glLoadIdentity();
     
        glTranslatef (0.0, 0.0, -5.0);
     
        // dessine le triangle
        glBegin (GL_TRIANGLES);
        glColor3f (1.0f, 0.0f, 0.0f);
        glVertex3f (-1.0f, -1.0f, 0.0f);
     
        glColor3f (0.0f, 1.0f, 0.0f);
        glVertex3f (1.0f, -1.0f, 0.0f);
     
        glColor3f (0.0f, 0.0f, 1.0f);
        glVertex3f (0.0f, 1.0f, 0.0f);
        glEnd ();
    }
     
    }
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
     
    #include "render.h"
     
    namespace rendering {
     
    Render::Render(const quint16 &framesPerSecond, const quint16 &interval_time) : QGLWidget()
    {
        //setWindowModality(Qt::ApplicationModal);
        setAttribute(Qt::WA_DeleteOnClose);
        QObject::connect(this, SIGNAL(WidgetClosed()), QApplication::instance(), SLOT(quit()));
     
        quint16 timerInterval = interval_time / framesPerSecond;
        t_Timer = new QTimer(this);
        connect(t_Timer, SIGNAL(timeout()), this, SLOT(timeOutSlot()));
        t_Timer->start( timerInterval );
     
        setAutoBufferSwap(true);
     
    }
     
    Render::~Render() {
       t_Timer->stop();
       delete t_Timer;
       t_Timer = nullptr;
    }
     
    void Render::closeEvent(QCloseEvent *event)
    {
          emit WidgetClosed();
          event->accept();
    }
     
    // to make a pause or to play
    void Render::change_play_pause(const bool &play_pause) {
    }
     
    bool Render::status_play_pause() {
        return play_pause;
    }
     
    void Render::timeOutSlot()
    {
        updateGL();
    }
     
    void Render::initializeGL()
    {
     
        // Les valeurs acceptées sont GL_MODELVIEW, GL_PROJECTION, et GL_TEXTURE
        glMatrixMode(GL_PROJECTION);
        // charge la matrice Identité
        glLoadIdentity();
        // Multiplie la matrice courante par la matrice perspective
        // left, right, bottom, top distance near, distance far
        glFrustum(-1, 1, -1, 1, 5, 7);
     
        // Retour au mode par défaut
        glMatrixMode(GL_MODELVIEW);
     
    }
     
    void Render::resizeGL(int width, int height)
    {
     
        // spécifie les dimensions de la fenêtre visible sous opengl
        QSize viewport_size = size();
        glViewport(0, 0, viewport_size.width(), viewport_size.height());
     
    }
     
    void Render::paintGL()
    {
    }
     
    }

  2. #2
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Sans les définitions de classes on ne peut appréhender les relations entre les types puisqu'on ne connaît ni la hiérarchie, ni les données membres. On est donc bien en mal de diagnostiquer tes symptômes.

    Aussi, on évite en général ce genre de gestion explicite de ressources en C++. Dans ton cas préfère une construction de type smart pointer.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 64
    Points : 40
    Points
    40
    Par défaut Voici les .h
    Voici les .h demandés. Sinon on ne peut pas m'aider c'est vrai

    Je remplace tous mes pointeurs par des pointeurs intelligents ? Merci

    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
     
    #ifndef TESTS_H
    #define TESTS_H
     
    #include "rendering/testsRender.h"
    #include <QThread>
     
    class Tests : public QObject
    {
        Q_OBJECT
    public:
        explicit Tests();
        ~Tests();
        void run_tests();
     
    private:
        rendering::TestsRender *testsRender;
     
    };
     
    #endif // TESTS_H
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    #ifndef TESTSRENDER_H
    #define TESTSRENDER_H
     
    #ifdef TESTS
     
    #include "testsuite.h"
    #include "testsOpengl.h"
    #include <QWidget>
    #include <thread>
     
    namespace rendering {
     
    class TestsRender: public QTestSuite {
         Q_OBJECT
     
    public:
        TestsRender();
        ~TestsRender();
     
        private:
        TestsOpengl *testsOpengl;
     
    private slots:
     
    };
     
    }
     
    #endif // TESTS
     
    #endif // TESTS_H
    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
     
    #ifndef TESTSOPENGL_H
    #define TESTSOPENGL_H
     
    #include "render.h"
     
    namespace rendering {
     
    class TestsOpengl: public Render {
     
    public:
        TestsOpengl(const quint16 &framesPerSecond, const quint16 &interval_time);
        ~TestsOpengl();
     
    protected:
        virtual void paintGL();
    };
    }
    #endif // TESTSOPENGL_H
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    #ifndef RENDER_H
    #define RENDER_H
     
    #include <QtOpenGL>
    #include <QGLWidget>
    #include <iostream>
     
    namespace rendering {
     
    class Render : public QGLWidget
    {
        Q_OBJECT
    public:
     
        // interval_time : interval time between each image
        Render(const quint16 &framesPerSecond, const quint16 &interval_time);
        ~Render();
     
        // to pause or run
        void change_play_pause(const bool &play_pause);
     
        // accesseurs
        bool status_play_pause();
     
    public slots:
        void timeOutSlot();
        void closeEvent(QCloseEvent *event);
     
    signals:
        void WidgetClosed();
     
    protected:
        QTimer *t_Timer;
        // play : true pause : false
        bool play_pause;
     
        virtual void initializeGL();
        virtual void resizeGL(int width, int height);
        virtual void paintGL();
     
    };
    }
     
    #endif // RENDER_H

  4. #4
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Le destructeur de Render n'est pas marqué virtual.

    Attention à la classe Tests : tu fais un delete testsRender; dans le destructeur sans initialiser testsRender dans le constructeur (même à nullptr). Si tu as le malheur de ne pas appeler la fonction d'allocation dans au moins l'un des flux d'exécutions possibles, tu t'exposes à un potentiel delete sur un pointeur invalide et non nul. Tu peux t'éviter cet écueil, et d'autres, en employant des std::unique_ptr et std::shared_ptr (ou l'équivalent Qt) à la place des pointeurs nus.

  5. #5
    Responsable Qt & Livres


    Avatar de dourouc05
    Homme Profil pro
    Ingénieur de recherche
    Inscrit en
    Août 2008
    Messages
    26 669
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur de recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 26 669
    Points : 188 683
    Points
    188 683
    Par défaut
    Déjà, as-tu besoin de pointeurs ?

    Citation Envoyé par Matt_Houston Voir le message
    (ou l'équivalent Qt)
    Pour info, un petit article sur les pointeurs intelligents de Qt (version 4) : http://qt-labs.developpez.com/pointe...-intelligents/

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 64
    Points : 40
    Points
    40
    Par défaut
    Merci,

    J'ai marqué virtual pour le destructeur de Render, je n'y avais pas pensé.
    J'ai fait un QSharedPointer sur testsRender qui ne respectait pas les règles RAII, merci .

    Mais j'ai toujours un "pure virtual method called terminate called without an active exception" venant de valgrind. Je ne sais pas si c'est bien grave

    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
    23
    24
     
    #include "tron.h"
    #include "tests.h"
     
    Tests::Tests() {
    }
     
    Tests::~Tests() {
    }
     
    void Tests::run_tests() {
     
        // Instanciation des classes pour lancer les tests
    //    maths::TestsVector testsVector;
        PTestsRender = QSharedPointer<rendering::TestsRender>(new rendering::TestsRender());
     
     
        std::vector<QObject*>::iterator iSuite;
        for (iSuite = QTestSuite::m_suites.begin(); iSuite != QTestSuite::m_suites.end(); ++iSuite)
        {
            QTest::qExec(*iSuite);
        }
     
    }
    Pour répondre à dourouc05 :

    J'aimerais bien éviter les pointeurs, mais si je ne le fais pas ma fenêtre QWidget sera aussitôt détruite.

Discussions similaires

  1. Réponses: 24
    Dernier message: 10/06/2005, 10h11
  2. Destructeur et wxWidgets
    Par elvivo dans le forum wxWidgets
    Réponses: 3
    Dernier message: 11/05/2005, 15h44
  3. destructeur et vector
    Par diefo dans le forum SL & STL
    Réponses: 14
    Dernier message: 02/03/2005, 12h15
  4. C++, string et valgrind
    Par Alcée dans le forum SL & STL
    Réponses: 4
    Dernier message: 07/01/2005, 00h19
  5. probleme avec valgrind
    Par bloops dans le forum Autres éditeurs
    Réponses: 5
    Dernier message: 26/11/2003, 22h49

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