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

Discussion :

Crash à l'ajout de membres

  1. #1
    Invité
    Invité(e)
    Par défaut Crash à l'ajout de membres
    Bonjour.

    J'ai un plantage très bizarre sur une fenêtre de mon application utilisant des QLineEdit.

    Ma classe de fenêtre est déclarée comme suit :

    EditAlerts.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class EditAlerts : public QDialog
    {
         public:
              EditAlerts();
     
         private:
              QGridLayout m_layout;
    }
    EditAlerts.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    EditAlerts::EditAlerts()
    {
         this->setLayout(&m_layout);
         m_layout.addWidget(new QLabel("Edit alerts", this), 0, 0, 1, 10);
     
         /* Instructions de création, je n'utilise pas QDesigner */
    }
    Juste là tout fonctionne très bien, mais si j'ai le malheur de déclarer un QLineEdit en membre de la classe :

    EditAlerts.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    private:
         QLineEdit m_min;
    Dans ce cas, alors mon application va crasher à la fermeture de la fenêtre (qui n'est pas le fenêtre principale). Et ce que j'utilise ou non ces QLineEdit.

    Et ce problème reste inchangé lorsque j'utilise des pointeurs plutôt que des objets en membres de la classe.
    Dernière modification par Invité ; 06/05/2013 à 11h56.

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

    Informations professionnelles :
    Activité : aucun

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

    En deux mots, c'est normal...

    Il faut savoir que chaque fois que tu utilise une fonction qui a pour but de placer un objet dans un autre, l'objet "récipiendaire" devient propriétaire de l'objet qu'on lui donne.

    En tant que propriétaire, il devient alors responsable de la durée de vie de l'objet qu'on lui a donné, qui ne pourra en aucun cas excéder celle du propriétaire.

    Or, Qt se base sur le fait que les objets que l'on transmet ont été créés de manière dynamique (avec new ), et considère donc qu'il faut impérativement appeler delete sur chaque objet.

    Seulement, m_layout (pour le premier cas) et m_min (dans le second) n'ont pas étés alloués de manière dynamique, et l'appel de delete sur un pointeur pointant sur un objet qui n'a pas été alloué dynamiquement (avec new) provoque un comportement indéfini, qui prend souvent la forme d'une erreur de segmentation.

    La bonne manière de travailler est donc d'utiliser des pointeurs sur des objets alloués de manière dynamique:
    EditAlerts.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class EditAlerts : public QDialog
    {
         public:
              EditAlerts();
     
         private:
              QGridLayout * m_layout;
              QLineEdit     * m_min;
    }
    EditAlerts.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    EditAlerts::EditAlerts()
    {
         m_min = new QLineEdit;
         m_layout = new QGridLayout;
         this->setLayout(m_layout);
         m_layout->addWidget(new QLabel("Edit alerts", this), 0, 0, 1, 10);
         m_layout->addWidget(m_min, /* ... */);
         /* Instructions de création, je n'utilise pas QDesigner */
    }
    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

  3. #3
    Invité
    Invité(e)
    Par défaut
    J'ai avais pensé, et j'avais déjà essayé, c'est ce que j'entendais par :
    Et ce problème reste inchangé lorsque j'utilise des pointeurs plutôt que des objets en membres de la classe.
    Maintenant, le problème s'est résolut lorsque mon membre de classe est passé de
    à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    QVector<QLineEdit*> m_min
    Il semblerait donc que je m'y soit mal pris la première fois.

    Mais j'ai donc plusieurs question, concernant les delete.
    Si j'ai un QGridLayout* m_layout, et que je l'ajoute à la fenetre avec setLayout, dois-je appeler delete dessus.
    Et lorsque j'ajoute les QLineEdit* au layout avec addWidget(), dois-je aussi les delete ensuite ?

  4. #4
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2009
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2009
    Messages : 1 009
    Par défaut
    http://qt-project.org/doc/qt-4.8/qwidget.html#setLayout
    The QWidget will take ownership of layout.
    http://qt-project.org/doc/qt-4.8/qlayout.html#addWidget
    http://qt-project.org/doc/qt-4.8/qlayout.html#addItem
    Note: The ownership of item is transferred to the layout, and it's the layout's responsibility to delete it.
    Facile, en lisant la doc

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Lelfic Voir le message
    J'ai avais pensé, et j'avais déjà essayé, c'est ce que j'entendais par :
    Et ce problème reste inchangé lorsque j'utilise des pointeurs plutôt que des objets en membres de la classe.
    Le seul fait d'utiliser des pointeurs n'est pas suffisant: un pointeur n'est jamais qu'une valeur numérique non signée qui représente "l'adresse mémoire à laquelle on trouvera un objet du type indiqué".

    Ce qu'il faut surtout, c'est faire en sorte que l'adresse en question corresponde à l'adresse mémoire à laquelle on trouvera un objet créé de manière dynamique (avec new).

    L'allocation dynamique de la mémoire pour ton objet (qu'il s'agisse du layout ou du QLineEdit) est indispensable pour s'assurer que Qt fonctionne correctement

    Le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    QVector<QLineEdit*> m_min;
    n'a de sens que si tu veux pouvoir disposer de plusieurs QLineEdit, mais il doit alors etre mis en relation avec un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    m_min.push_back(new QLineEdit(/*...*/));
    dans la (ou les) fonction(s) qui s'occupe(nt) de créer plusieurs champs d'éditions
    Mais j'ai donc plusieurs question, concernant les delete.
    Si j'ai un QGridLayout* m_layout, et que je l'ajoute à la fenetre avec setLayout, dois-je appeler delete dessus.
    Et lorsque j'ajoute les QLineEdit* au layout avec addWidget(), dois-je aussi les delete ensuite ?
    Surtout pas, malheureux...

    Quand tu invoque setLayout, le widget au départ duquel tu invoques cette fonction va:
    • correctement détruire le widget qu'il utilisait avant
    • devenir propriétaire du layout que tu lui transmet
    Lorsque le widget sera détruit, il détruira correctement le layout dont il est propriétaire (donc, celui que tu lui auras donné en appelant la fonction setLayout).

    De même, lorsque tu invoque la fonction addWidget (ou addLayout) d'un layout, le layout devient propriétaire du widget (ou du layout) que tu lui as ajouté.

    En tant que layout propriétaire, il veillera à détruire les objets dont il est propriétaire au moment où il sera détruit

    Avec ce système, lorsque la fenêtre principale (ou toute autre fenetre / boite de dialogue / ...) est détruite, elle détruit le layout dont elle est propriétaire, et la destruction du layout occasionne la destruction de tout ce qu'il contient, le tout de manière récursive jusqu'à ce que tous les éléments graphiques contenus par la fenêtre / la boite de dialogue soient détruits
    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

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 23/01/2014, 17h08
  2. [WS 2008 R2] Problème pour ajouter un membre à un groupe sous Powershell
    Par jaymzwise dans le forum Windows Serveur
    Réponses: 7
    Dernier message: 09/07/2013, 11h11
  3. [OL-2003] Ajouter des membres dans une liste de diffusion
    Par megapacman dans le forum VBA Outlook
    Réponses: 0
    Dernier message: 21/11/2011, 11h53

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