2015-07-14 1 views
4

Je le cas d'utilisation suivant (ne pas vraiment de sens, car il est réduit au minimum à partir d'un exemple de la vie active, mais je pense qu'il est encore techniquement correct):Est-ce que Q3ListView ne se désinscrit pas du magasin de sauvegarde Qt ou que le code est incorrect?

class Dialog : public QDialog 
{ 
public: 
    Dialog(QWidget* parent) 
    : QDialog(parent) 
    { 
     new Q3ListView(this); // this will crash 
// new QWidget(this); // this won't crash 
    } 
}; 

En fonction de ce qui est ajouté à la Dialog le programme se bloque ou non lors de la suppression de l'instance Dialog (comme indiqué par les commentaires dans l'extrait), mais uniquement lorsque les indicateurs de la fenêtre principale ont été modifiés. Voici le code pour la classe MainWindow, qui utilise Dialog:

class MainWindow : public QMainWindow 
{ 
public: 
    // the fact that the widget (dialog) below 
    // has no chance to show seems irrelevant. 
    // In the real scenario I have, the widget is shown on 
    // the screen and is closed by the user. 
    // I've just put the whole sequence of pieces of code 
    // that result from signal/slot calls, that in turn 
    // result from a point&click scenario in our application 
    // into the following function for brevity. 
    void go() 
    {   
     auto dialog = new Dialog(this); 
     dialog->show(); 
     dialog->close(); 

     disableAlwaysOnTop(); 

     delete dialog; // or dialog->deleteLater(); 
    } 

    void disableAlwaysOnTop() 
    { 
     setAttribute(Qt::WA_Resized, true); 

     Qt::WindowFlags flags = windowFlags(); 
     setWindowFlags(flags^(Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint)); 

     setVisible(true); 
    } 
}; 

et la mise en œuvre de main:

int main(int argc, char** argv) 
{ 
    QApplication app(argc, argv); 
    MainWindow mainWindow; 
    mainWindow.show(); 
    mainWindow.go(); 
    return app.exec(); 
} 

Toutes les lignes semblent essentielles pour reproduire l'accident.

Est-ce un bug dans Qt, ou est-ce que je fais quelque chose de mal?

La suppression manuelle des enfants du widget est autorisée, et ils doivent automatiquement se désinscrire de leurs parents, comme indiqué dans la citation du manuel ci-dessous. Dans mon cas réel, le widget est supprimé pour disparaître de l'interface graphique, et il fonctionne dans le cas d'autres combinaisons de widgets. Comme indiqué dans le commentaire ci-dessus, changer delete dialog; à dialog->deleteLater(); n'aide pas.

Il semble qu'il y ait un problème pour éliminer l'instance Q3ListView du magasin de support de Qt, voici la trace de la pile:

QtGuid4.dll QWidgetBackingStore :: staticContents (QWidget * parent, const QRect & withinClipRect) ligne 499 C++

QtGuid4.dll! QWidgetBackingStore :: sync() ligne 1200 C++

QtGuid4.dll! QWidgetPrivate :: syncBackingStore() ligne 1896 C++

QtGuid4.dll! QWidget :: événement (QEvent * event) Ligne C++ 8694

QtGuid4.dll! QMainWindow :: event (QEvent * event) Ligne C++ 1479

QtGuid4.dll! QApplicationPrivate :: notify_helper (QObject * récepteur, QEvent * e) ligne C++ 4565

QtGuid4.dll! QApplication :: Notify (récepteur QObject *, QEvent * e) ligne C++ 4530

QtCored4.dll! QCoreApplication :: notifyInternal (Récepteur QObject *, événement QEvent *) Ligne 955 C++

QtCored4.dll! QCoreApplication :: sendEvent (récepteur QObject *, QEvent * event) Ligne 231 C++

QtCored4.dll! QCoreApplicationPrivate :: sendPostedEvents (QObject * récepteur, int event_type, QThreadData * Données) Ligne C++ 1579

QtCored4.dll!qt_internal_proc (HWND__ * hwnd, message non signé int, wp __int64 non signé, __int64 lp) Ligne 498 C

++

[Code externe]

QtCored4.dll! QEventDispatcherWin32 :: processEvents (drapeaux de QFlags) Ligne 823 C++

QtGuid4.dll! QGuiEventDispatcherWin32 :: processEvents (drapeaux QFlags) ligne C++ 1216

QtCored4.dll! QEventLoop :: processEvents (drapeaux de QFlags) ligne 150 C++

QtCored4.dll! QEventLoop :: exec (QFlags drapeaux Ligne 20 4 C++

QtCored4.dll! QCoreApplication :: exec() Ligne C++ 1227

QtGuid4.dll! QApplication :: exec() Ligne C++ 3824

qt_bug.exe! Main (int argc, char * * argv) ligne 60 C++

et le morceau de code de Qt qui tente d'utiliser un pointeur vers un objet supprimé dans la ligne indiquée dans la trace de pile:

for (int i = 0; i < count; ++i) { 
    QWidget *w = staticWidgets.at(i); 
    QWidgetPrivate *wd = w->d_func(); 
    if (!wd->isOpaque || !wd->extra || wd->extra->staticContentsSize.isEmpty() // **** 
     || !w->isVisible() || (parent && !parent->isAncestorOf(w))) { 
     continue; 
    } 

(wd pointe vers un objet supprimé sur la ligne marquée du commentaire).

Avertissement: Je sais que plus des solutions élégantes existent, mais c'est le code existant, et selon Qt's manual:

Vous pouvez également supprimer enfant vous-même des objets, et ils se retirer de leurs parents.

ce code est valide.

Nous avons reproduit le problème sous Windows 7 (MSVC 2010 SP1, CL16), Windows 8 (MSVC 2013 U4, CL18) et Fedora 20 (GCC 4.8.3).

+0

a une vraie bug Qt. C'est un cas de coin: il semble que vous ne devriez pas supprimer les widgets instanciés et affichés avant que la boucle d'événement n'ait une chance de s'exécuter. Je ne pense pas que ce soit spécifique à Q3ListView. Mon pari est que si vous changez 'delete dialog' en' dialog-> deleteLater() ', il ne se bloquera pas. Peut-être que si vous insérez 'qApp-> processEvents()' avant le 'delete', il ne se bloquera pas non plus. S'il vous plaît, dites-nous sur quelle plateforme il est, car c'est important aussi. Je pourrais essayer de le reproduire. –

+0

TL; DR: Votre code n'est pas faux, mais je doute qu'il y ait beaucoup de tests dans la base de code Qt pour s'assurer que les widgets affichés affichés peuvent être supprimés avant que la boucle d'événements ne soit drainée. Je parie que de telles manigances pourraient aussi tomber en panne à Qt 5. –

+0

@KubaOber Merci pour votre contribution. J'ai oublié de mentionner que j'ai essayé 'dialog-> deleteLater()' et malheureusement cela n'aide pas. Nous avons reproduit le crash sur Windows 7, Windows 8 et Arch Linux. Je vais mettre à jour la question. – BartoszKP

Répondre

0

J'ai déposé un bug report. Comme il s'agit d'une ancienne version de la bibliothèque, on ne peut espérer qu'elle soit corrigée.

Nous supprimons qt3support de toute façon et donc tout le monde est conseillé successivement;)