我目前陷入赛格(有时由于糟糕的mallocs ageabrts),每当我尝试将qtring添加到qmap作为qmap中的qmap,我认为qwidget类的析构函数 - 我认为它与qstring的隐式有关共享模型和范围。

我有一个quidget作为mdi中的子窗口,这个qwidget有一些qglwidget派生视口实例作为孩子。在子窗口中有一个qmap 包装类包含项目文件设置的类,当子窗口关闭时,它的析构函数调用qwidget :: deletechildren()删除每个视口的删除。在视口析构函数中,当前设置将保存到子窗口的设置中,例如:

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

swin.setsetting()被调用我希望保存的每个属性,“swin”是对QMAP包装类的引用,该类被删除在子窗口析构函数的末尾。一切都很好,直到setSetting()呼叫,即:

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

此设置为第一个视口工作,在第一个setSetting()调用第二个视图中,egfault发生在:

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

当我的qstring引用传递给qmap时,我看到一个深副本失败?如果是这样,为什么?当析构函数没有返回时,我创建的QString并没有超出范围。为什么这会在第二个视口上失败,而不是第一个?

偶尔,我将获得一个sigabrt malloc():内存损坏在第一个代码示例的setsetting()行中的运算符+中。但再次,在第二个视口的销毁开始时,不是第一个。

我为非常勇气的问题道歉,但是涉及许多翻译单位的大量代码。这个问题的任何线索都会有很大的帮助!

提前感谢。 凸轮


更新

我将我的第一个代码样本更改为:

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

作为对范围问题的测试。它有时工作,其他时间给出了完全相同的错误;因此,大概是堆被销毁的堆QString,它只是取决于它是否已被覆盖。但这也没有意义,因为我不打电话给它,我没有关闭应用程序(只是一个MDI子窗口)!


更多代码

在实例化新子窗口时在堆上创建swin。它被引入了视口类'析构函数作为来自我的子窗口的方法的参考:

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

sy_project是(当前)一个简单的qmap类类。我的完整视图基类析构函数是这样(它在这里失败,不在派生类中):

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

使用Valgrind的Memcheck后,我发现了许多看起来与我的堆栈特有的条目。在之前从未使用过,我还在解密,但这就是说我的sy_project类(qmap的包装包装)已被删除 setsetting()呼叫离开qmap与无效的引用?

==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)
.

有帮助吗?

解决方案

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.

其他提示

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...

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top