variable not accessible problem. Fixes found dont work
-
I have encountered a runtime error which while debugging list a variable as not accessible. there are other post on this subject but the fixes do not work for me.
I use QtCreator 4.5.1 and Qt lib 5.10 (Mingw32 5.3, MSVC14 x64, MSVC x64)
I have disabled "Load system GDB pretty printers" as suggested in
disable pretty printers post
.Intent of failing code:
In order to communicate between my decoupled QtQuick2 viewmodels I implemented a simple version of the EventAgregator pattern.
the implementation is still missing thread safty and clean up of no longer existing subscribers. however it is not relevant for my error.
break point at error to be thrown and current watch list
relevant code files:
qspinstartup.h
class QSpinStartup:QObject { public: QSpinStartup(); bool loadQSpin(const QString dir, const QString startView=""); private: void registerQmlGui(); void registerQmlViewModel(); QQmlApplicationEngine engine; //constant viewmodel objects CodeEditorTab* codeEditor; VerificationTab* verificationEditor; QSpinMessageService msgService; };
qspinstartup.cpp
QSpinStartup::QSpinStartup():QObject() ,verificationEditor(new VerificationTab(msgService,this)) ,codeEditor(new CodeEditorTab(msgService,this)) //,console(new ConsoleEditor(msgService,this)) { registerQmlGui(); registerQmlViewModel(); initPointerObjects(); auto ctx = engine.rootContext(); qSpinNullPtrCheck(ctx); PrintToConsole p("pri"); msgService.publish<PrintToConsole>(p); ctx->setContextProperty("codeEditorVm",codeEditor); } bool QSpinStartup::loadQSpin(const QString dir,const QString startView) { QDir ldir(dir); QString l = ldir.entryList(QStringList()<<startView,QDir::Files).first(); qInfo()<<l; engine.load(QUrl(l.prepend("qrc:/"))); bool isReady = engine.rootObjects().count()>0; qSpinSafeFail(!isReady,"Qml Application failed to start engine"); return isReady; } void QSpinStartup::registerQmlGui() { QSpinWorkSpace::Workspace::registerAsQml(); } void QSpinStartup::registerQmlViewModel() { VerificationTab::registerAsQml(); CodeEditorTab::registerAsQml(); ConsoleEditor::registerAsQml(); }
ieventbase.h
class IEventBase{ public: enum Types{ // <--simple way to give an object a type specifier PrintToConsole, CurrentDocumentChanged, CompilerOptions, SpinArgCommand }; IEventBase(Types t):type(t){} const Types type; };
qspinmessageservice.h
template<class T> class ISubscriber{ public: virtual ~ISubscriber(){} virtual void executeSubscribed(T& event)=0; }; class QSpinMessageService: public QObject{ Q_OBJECT typedef QPointer<QObject> subscriber; typedef QVector<subscriber> EvAgrList; QHash<IEventBase::Types,EvAgrList> subs; public: QSpinMessageService(QObject* parent=nullptr):QObject(parent) ,subs(QHash<IEventBase::Types,EvAgrList>()){} void subscribe(QObject *obj, IEventBase::Types key){ if(!subs.contains(key)) // <-- this line cause my error subs[key]= EvAgrList(); EvAgrList& list = subs[key]; list<<subscriber(obj); } template<typename T> void publish(typename T::IEventBase execute){ EvAgrList lSubs = subs[execute.type]; for(int i=0; i<lSubs.count();i++){ subscriber&q = lSubs[i]; if(q.isNull()){ lSubs.removeOne(q); --i; continue; } ISubscriber<T>* a = dynamic_cast<ISubscriber<T>*>(q.data()); qDebug()<< q<<a; //ISubscriber<T>* s = dynamic_cast<ISubscriber<T>*>(q); a->executeSubscribed(static_cast<T&>(execute)); } } }; static QSpinMessageService dummy;
verificationtab.cpp (its a big class so i excluded irrelevant parts)
VerificationTab::VerificationTab(QSpinMessageService &service, QObject *parent) : QSpinTab(parent,"Verification",QSpinTabType::Verification) ,msgService(service) ,m_stateProp(new StateSpaceProp(this)),m_stateSpec(new StateSpaceSpec(this)) ,m_memoryUsage(new MemoryUsage(this)),m_settings(new VerificationSettings(this)) { msgService.subscribe(this,IEventBase::CurrentDocumentChanged); // <-- error call //if the line above is commented out the application runs }
Github repository of the full application
note:
I Designed the QSpinMessageService in seperate empty project, before adding the files to the main project. the subcribe methods works in that project.
Any idea of how to fix this?
-
I finally located the cause of my error. Despite the fact that the Debug Watch list indicate That the QSpinMessageService object exist, It havent been propberly initialized yet at this point.
Why subscribe() is even able to be accessed is beyond my current cpp skills.The fix:
In qspinstartup.cpp the construtor need to be changed as follows.QSpinStartup::QSpinStartup():QObject() { codeEditor = new CodeEditorTab(msgService,this); verificationEditor = new VerificationTab(&msgService,this); registerQmlGui(); registerQmlViewModel(); auto ctx = engine.rootContext(); qSpinNullPtrCheck(ctx); PrintToConsole p("pri"); msgService.publish<PrintToConsole>(p); ctx->setContextProperty("codeEditorVm",codeEditor); }