В настоящее время я застрял в отношении segfaults (иногда sigabrts из-за неправильных malloc), когда я пытаюсь добавить QString в QMap в качестве ключа внутри деструктора класса QWidget, который у меня есть - я думаю, что это как-то связано с неявным QStringмодель и область совместного использования.
У меня есть QWidget, выступающий в качестве подокна в 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 () второго,segfault происходит по адресу:
inline QString::QString(const QString &other) : d(other.d)
{ Q_ASSERT(&other != this); d->ref.ref(); }
Я не вижу глубокой копии, когда моя ссылка на QString передается в QMap?Если так, то почему?Созданная мной QString еще не вышла из области видимости, поскольку деструктор не вернулся.И почему бы это не сработало во втором окне просмотра, а не в первом?
Иногда я получаю sigabrt malloc (): повреждение памяти в операторе + в строке setSetting () первого кодапример .Но опять же, в начале уничтожения второго видового экрана, а не первого.
Я прошу прощения за очень многословный вопрос, но существует большое количество кода, разбросанного по многим единицам перевода.Любые подсказки для этой проблемы были бы большой помощью!
Заранее спасибо.Cam
Обновление
Я изменил свой первый пример кода на:
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
После использования memcheck от Valgrind Iобнаружил многочисленные записи, похожие на мою трассировку стека.Никогда прежде не использовав его, я все еще расшифровываю, но означает ли это, что мой класс 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)