c++ - QString errors when copying into QMap. Scope issue? -
i'm stuck regards segfaults (sometimes sigabrts due bad mallocs) whenever try add qstring qmap key inside destructor of qwidget class have - think has qstring's implicit sharing model , scope.
i have qwidget acting sub window in mdi, qwidget has few qglwidget derived viewport instances children. in sub window there qmap< qstring, qvariant > wrapper class contains project file's settings, when sub window closed, it's destructor calls qwidget::deletechildren() deletes each of viewports. in viewport destructor current settings saved sub window's settings, eg:
qstring dir = qstring( "camera/" ) + name; swin.setsetting( dir + "/projection", static_cast< int >( camera_->getprojectiontype() ) );
the swin.setsetting() called each of properties wish save, 'swin' reference qmap wrapper class deleted @ end of sub window destructor. fine until setsetting() call, just:
inline void setsetting( const qstring& key, qvariant value ) { // projectsettings_ standard qmap< qstring, qvariant >. projectsettings_.insert( key, value ); }
this setup works fine for first viewport, @ first setsetting() call of second, segfault occurs at:
inline qstring::qstring(const qstring &other) : d(other.d) { q_assert(&other != this); d->ref.ref(); }
am seeing deep copy fail when qstring reference passed qmap? if so, why? qstring created has not gone out of scope yet destructor has not returned. , why fail on second viewport , not first?
occasionally sigabrt malloc(): memory corruption in operator+ in setsetting() line of first code example . again, @ start of second viewport's destruction, not first.
i apologise wordy question, there large amount of code involved spread across many translation units. clues problem great help!
thanks in advance. cam
update
i changed first code sample to:
qstring* dir = new qstring( "camera/" ); *dir += name; swin.setsetting( *dir + "/projection", static_cast< int >( camera_->getprojectiontype() ) );
as test scope issues. , sometimes works, , other times gives same error; presumably heap qstring being destroyed, depends on whether or not it's memory location has been overwritten. makes no sense, not calling delete on it, nor closing application (just mdi sub window)!
more code
swin created on heap when new sub window instantiated. brought viewport class' destructor reference method sub window:
inline sy_project& getproject() { return *project_; }
sy_project (currently) simple wrapper class qmap. complete viewport base class destructor (it fails here, not in derived class):
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
after using valgrind's memcheck discovered numerous entries looked similar stacktrace. having never used before, i'm still deciphering, saying sy_project class (wrapper qmap) has been deleted after setsetting() call leaving qmap invalid reference?
==12418== invalid read of size 4 ==12418== @ 0x805d872: qmap<qstring, qvariant>::detach_helper() (qmap.h:730) ==12418== 0x805d380: qmap<qstring, qvariant>::detach() (in /home/cbamber85/workspace/syren gui/syren) ==12418== 0x805cdee: qmap<qstring, qvariant>::insert(qstring const&, qvariant const&) (qmap.h:537) ==12418== 0x805ca33: sy_project::setsetting(qstring const&, qvariant) (sy_project.h:50) ==12418== 0x805a78c: sy_abstractglviewport::~sy_abstractglviewport() (sy_abstractglviewport.cpp:67) ==12418== 0x808edbc: sy_qtglviewport::~sy_qtglviewport() (sy_qtglviewport.cpp:91) ==12418== 0x808ee0e: sy_qtglviewport::~sy_qtglviewport() (sy_qtglviewport.cpp:100) ==12418== 0x4d66d63: qobjectprivate::deletechildren() (in /usr/lib/libqtcore.so.4.6.3) ==12418== 0x4306ddf: qwidget::~qwidget() (in /usr/lib/libqtgui.so.4.6.3) ==12418== 0x46fbe0e: qframe::~qframe() (in /usr/lib/libqtgui.so.4.6.3) ==12418== 0x475f173: qsplitter::~qsplitter() (in /usr/lib/libqtgui.so.4.6.3) ==12418== 0x475f1d1: qsplitter::~qsplitter() (in /usr/lib/libqtgui.so.4.6.3) ==12418== address 0xacf5b9c 4 bytes inside block of size 8 free'd ==12418== @ 0x40266ad: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==12418== 0x808d60f: sy_project::~sy_project() (sy_project.h:30) ==12418== 0x808c9c6: sy_subwindow::~sy_subwindow() (sy_subwindow.cpp:55) ==12418== 0x808ca84: sy_subwindow::~sy_subwindow() (sy_subwindow.cpp:57) ==12418== 0x4d66482: qdeleteineventhandler(qobject*) (in /usr/lib/libqtcore.so.4.6.3) ==12418== 0x4d67967: qobject::event(qevent*) (in /usr/lib/libqtcore.so.4.6.3) ==12418== 0x4302acb: qwidget::event(qevent*) (in /usr/lib/libqtgui.so.4.6.3) ==12418== 0x42a9c63: qapplicationprivate::notify_helper(qobject*, qevent*) (in /usr/lib/libqtgui.so.4.6.3) ==12418== 0x42b1ca3: qapplication::notify(qobject*, qevent*) (in /usr/lib/libqtgui.so.4.6.3) ==12418== 0x806010f: sy_application::notify(qobject*, qevent*) (sy_application.cpp:14) ==12418== 0x4d54e0d: qcoreapplication::notifyinternal(qobject*, qevent*) (in /usr/lib/libqtcore.so.4.6.3) ==12418== 0x4d589b3: qcoreapplicationprivate::sendpostedevents(qobject*, int, qthreaddata*) (in /usr/lib/libqtcore.so.4.6.3)
i think sy_project object pointer , therefore references pointing destroyed time destructor of sy_abstractglviewport called. if valgrind listing, destructor of sy_project called before destructor of sy_abstractglviewport.
so when call inline sy_project& getproject() { return *project_; }
within sy_abstractglviewport destructor, you're dereferencing dangling pointer.
Comments
Post a Comment