Question

Je suis actuellement coincé en ce qui concerne les segfault (parfois des Sigabrts dues à de mauvais maslocs) chaque fois que j'essaye d'ajouter un qstring à un QMAP en tant que clé à l'intérieur du destructeur de la classe QWidget, je pense qu'il a quelque chose à voir avec implicite de Qstring Modèle de partage et portée.

J'ai un qwidget agissant comme une sous-fenêtre dans un MDI, ce QWidget a quelques instances de visionnement dérivées Qglwidget en tant qu'enfants. Dans la sous-fenêtre, il existe une classe qmap wrapper contenant les paramètres du fichier du projet, lorsque la sous-fenêtre est fermée, les appels destructeurs QWidget :: Supprenetechildren () qui supprime chacun des fenêtres. Dans le destructeur de la fenêtre de vue, les paramètres actuels sont enregistrés dans les paramètres de la sous-fenêtre, par exemple:

QString dir = QString( "camera/" ) + name;
sWin.setSetting( dir + "/Projection",
                 static_cast< int >( camera_->getProjectionType() ) );

Le swin.setsetting () est appelé à chacune des propriétés que je souhaite enregistrer, "Swin" est une référence à la classe wrapper QMAP supprimée à la fin du destructeur de sous-fenêtre. Tout va bien jusqu'à l'appel de plonget (), qui est juste:

inline void setSetting( const QString& key, QVariant value )
{
    //  projectSettings_ is a standard QMap< QString, QVariant >.
    projectSettings_.insert( key, value );
}

Cette configuration fonctionne bien pour le premier point de vue , à la première appel de la seconde () de la seconde, un Segfault se produit à l'adresse suivante:

inline QString::QString(const QString &other) : d(other.d)
{ Q_ASSERT(&other != this); d->ref.ref(); }

suis-je en train de voir une copie profonde échec lorsque ma référence Qstring est transmise au QMAP? Si oui, pourquoi? Le QString que j'ai créé n'a pas encore disparu de la portée, car le destructeur n'est pas retourné. Et pourquoi cela échouerait-il sur la deuxième fenêtre et non le premier?

occasionnellement, je recevrai un SIGABRT MALLOC (): Corruption de la mémoire dans l'opérateur + dans la ligne de plongetage () de la première exemple de code. Mais encore une fois, au début de la destruction du deuxième viewport, pas le premier.

Je m'excuse pour la question très verbale, mais il existe une grande quantité de code impliquée dans de nombreuses unités de traduction. Tous les indices de ce problème seraient une grande aide!

Merci d'avance. Cam


mise à jour

J'ai changé mon premier échantillon de code à:

QString* dir = new QString( "camera/" );
*dir += name;
sWin.setSetting( *dir + "/Projection",
                 static_cast< int >( camera_->getProjectionType() ) );

Un test de périmètre. Et il parfois fonctionne et d'autres fois donne exactement la même erreur; Donc, vraisemblablement, le tas Qstring est en train d'être détruit, cela dépend simplement de savoir si l'emplacement de la mémoire est écrasé ou non. Mais cela n'a également aucun sens, car je ne l'appelle pas de la supprime, ni je ferme la demande (juste une sous-fenêtre MDI)!


plus de code

Swin est créé sur le tas lorsque une nouvelle sous-fenêtre est instanciée. Il est introduit dans le destructeur de la classe Viewport comme référence d'une méthode de ma sous-fenêtre:

inline Sy_project& getProject() { return *project_; }

sy_project est (actuellement) une classe d'emballage simple pour QMAP. Mon destructeur de classe de base de la fenêtre complète est-ce (il échoue ici, pas dans la classe dérivée):

Sy_abstractGLViewport::~Sy_abstractGLViewport()
{
    //  Write last viewport settings.
    QString name = objectName();
    Sy_project& sWin = projWindow_->getProject();
    QString dir = QString( "camera/" ) + name;

    //  Avoid "taking address of temporary" warning.
    QVector3D pos = camera_->getPosition();
    QVector3D foc = camera_->getFocalPoint();

    //  Save camera settings.  Dies on first setSetting() call.
    sWin.setSetting( dir + "/Projection",
                     static_cast< int >( camera_->getProjectionType() ) );
    sWin.setSetting( dir + "/position",
                     QVariant( 84, static_cast< void* >( &pos ) ) );
    sWin.setSetting( dir + "/focalPoint",
                     QVariant( 84, static_cast< void* >( &foc ) ) );
    sWin.setSetting( dir + "/FOV", camera_->getFOV() );
    sWin.setSetting( dir + "/nearClip", camera_->getPerspectiveClipRange()[0] );
    sWin.setSetting( dir + "/farClip", camera_->getPerspectiveClipRange()[1] );

    delete camera_;
}


Valgrind

Après avoir utilisé Memcheck de Valgrind, j'ai découvert de nombreuses entrées similaires à mon stacktrace. Ne jamais l'utiliser auparavant, je déchiffre toujours, mais cela dit-il que ma classe Sy_Project (wrapper pour QMAP) a été supprimée après l'appel de plonget () quittant QMAP avec une référence invalide?

==12418== Invalid read of size 4
==12418==    at 0x805D872: QMap<QString, QVariant>::detach_helper() (qmap.h:730)
==12418==    by 0x805D380: QMap<QString, QVariant>::detach() (in /home/cbamber85/workspace/Syren GUI/Syren)
==12418==    by 0x805CDEE: QMap<QString, QVariant>::insert(QString const&, QVariant const&) (qmap.h:537)
==12418==    by 0x805CA33: Sy_project::setSetting(QString const&, QVariant) (Sy_project.h:50)
==12418==    by 0x805A78C: Sy_abstractGLViewport::~Sy_abstractGLViewport() (Sy_abstractGLViewport.cpp:67)
==12418==    by 0x808EDBC: Sy_QtGLViewport::~Sy_QtGLViewport() (Sy_QtGLViewport.cpp:91)
==12418==    by 0x808EE0E: Sy_QtGLViewport::~Sy_QtGLViewport() (Sy_QtGLViewport.cpp:100)
==12418==    by 0x4D66D63: QObjectPrivate::deleteChildren() (in /usr/lib/libQtCore.so.4.6.3)
==12418==    by 0x4306DDF: QWidget::~QWidget() (in /usr/lib/libQtGui.so.4.6.3)
==12418==    by 0x46FBE0E: QFrame::~QFrame() (in /usr/lib/libQtGui.so.4.6.3)
==12418==    by 0x475F173: QSplitter::~QSplitter() (in /usr/lib/libQtGui.so.4.6.3)
==12418==    by 0x475F1D1: QSplitter::~QSplitter() (in /usr/lib/libQtGui.so.4.6.3)
==12418==  Address 0xacf5b9c is 4 bytes inside a block of size 8 free'd
==12418==    at 0x40266AD: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==12418==    by 0x808D60F: Sy_project::~Sy_project() (Sy_project.h:30)
==12418==    by 0x808C9C6: Sy_subWindow::~Sy_subWindow() (Sy_subWindow.cpp:55)
==12418==    by 0x808CA84: Sy_subWindow::~Sy_subWindow() (Sy_subWindow.cpp:57)
==12418==    by 0x4D66482: qDeleteInEventHandler(QObject*) (in /usr/lib/libQtCore.so.4.6.3)
==12418==    by 0x4D67967: QObject::event(QEvent*) (in /usr/lib/libQtCore.so.4.6.3)
==12418==    by 0x4302ACB: QWidget::event(QEvent*) (in /usr/lib/libQtGui.so.4.6.3)
==12418==    by 0x42A9C63: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/lib/libQtGui.so.4.6.3)
==12418==    by 0x42B1CA3: QApplication::notify(QObject*, QEvent*) (in /usr/lib/libQtGui.so.4.6.3)
==12418==    by 0x806010F: Sy_application::notify(QObject*, QEvent*) (Sy_application.cpp:14)
==12418==    by 0x4D54E0D: QCoreApplication::notifyInternal(QObject*, QEvent*) (in /usr/lib/libQtCore.so.4.6.3)
==12418==    by 0x4D589B3: QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (in /usr/lib/libQtCore.so.4.6.3)

Était-ce utile?

La solution

I think the Sy_project object your pointer and therefore references are pointing to is already destroyed by the time the destructor of Sy_abstractGLViewport is called. If you look into the valgrind listing, the destructor of Sy_project is called before the destructor of Sy_abstractGLViewport.

So when you call inline Sy_project& getProject() { return *project_; } within the Sy_abstractGLViewport destructor, you're dereferencing a dangling pointer.

Autres conseils

Hum... What happens if you change your code for something like this:

dir.append("/Projection");
sWin.setSetting(dir, static_cast<int>(camera_->getProjectionType()));

In the way you are doing a temporary copy is create and then bound to a reference-to-const, which should be ok. Afterwards, from this reference QMap will attempt to copy the argument, in this case, going through the implicit sharing mechanism of QString. I'm just wondering what could go wrong in there...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top