Adding a virtual function causes strange result...
-
@jsulm :
1 QListData::size() const qlist.h 115 0x10000799f 2 QList<std::pair<QString, QString>>::length() const qlist.h 360 0x100043265 3 clsXMLnode::strGetAttribute(QString) clsMainWnd.cpp 4281 0x100028276 4 clsQtLayout::addButton(QAbstractButton *, QString const&) clsQtLayout.cpp 149 0x10008ad47 5 clsXMLnode::setWidget(QWidget *) clsMainWnd.cpp 3860 0x10002b026 6 clsQtRadioButton::clsQtRadioButton(clsXMLnode *, QString *, QWidget *) clsQtRadionButton.cpp 40 0x1000a6a8f 7 clsQtRadioButton::clsQtRadioButton(clsXMLnode *, QString *, QWidget *) clsQtRadionButton.cpp 38 0x1000a993d 8 clsCNT::pCreate(clsXMLnode *, QString const&, QString&, QStringList&, QWidget *) clsCNT.cpp 141 0x100005f59 9 clsXMLnode::clsXMLnode(QStringList&, clsXMLnode *) clsMainWnd.cpp 766 0x1000232c9 10 clsXMLnode::clsXMLnode(QStringList&, clsXMLnode *) clsMainWnd.cpp 545 0x10002ed35 11 clsScriptHelper::addNodesToGUI(clsXMLnode *, QLayout *, QJsonArray&, int *, int *) clsScriptHelper.cpp 317 0x1000bf08b 12 clsScriptHelper::addNodesToGUI(clsXMLnode *, QLayout *, QJsonArray&, int *, int *) clsScriptHelper.cpp 419 0x1000bfed7 13 clsScriptHelper::addNodesToGUI(clsXMLnode *, QLayout *, QJsonArray&, int *, int *) clsScriptHelper.cpp 419 0x1000bfed7 14 clsScriptHelper::addGUIelement(QJsonObject const&) clsScriptHelper.cpp 232 0x1000bd8c2 15 clsScriptHelper::qt_static_metacall(QObject *, QMetaObject::Call, int, void * *) moc_clsScriptHelper.cpp 216 0x1000dae2a 16 clsScriptHelper::qt_metacall(QMetaObject::Call, int, void * *) moc_clsScriptHelper.cpp 303 0x1000db8dc 17 CallMethod(QQmlObjectOrGadget const&, int, int, int, int *, QV4::ExecutionEngine *, QV4::CallData *, QMetaObject::Call) qv4qobjectwrapper.cpp 1301 0x1012bf559 18 CallPrecise(QQmlObjectOrGadget const&, QQmlPropertyData const&, QV4::ExecutionEngine *, QV4::CallData *, QMetaObject::Call) qv4qobjectwrapper.cpp 1569 0x1012bb753 19 QV4::QObjectMethod::callInternal(QV4::Value const *, QV4::Value const *, int) const qv4qobjectwrapper.cpp 2131 0x1012bafda 20 QV4::FunctionObject::call(QV4::Value const *, QV4::Value const *, int) const qv4functionobject_p.h 202 0x1012e97bc 21 QV4::Runtime::CallProperty::call(QV4::ExecutionEngine *, QV4::Value const&, int, QV4::Value *, int) qv4runtime.cpp 1448 0x1012e9799 22 QV4::Moth::VME::interpret(QV4::CppStackFrame *, QV4::ExecutionEngine *, const char *) qv4vme_moth.cpp 727 0x1012d56b0 23 QV4::Moth::VME::exec(QV4::CppStackFrame *, QV4::ExecutionEngine *) qv4vme_moth.cpp 463 0x1012d4542 24 QV4::ArrowFunction::virtualCall(QV4::FunctionObject const *, QV4::Value const *, QV4::Value const *, int) qv4functionobject.cpp 528 0x10127d8cf 25 QV4::FunctionObject::call(QV4::Value const *, QV4::Value const *, int) const qv4functionobject_p.h 202 0x1012e9578 26 QV4::Runtime::CallName::call(QV4::ExecutionEngine *, int, QV4::Value *, int) qv4runtime.cpp 1406 0x1012e9562 27 QV4::Moth::VME::interpret(QV4::CppStackFrame *, QV4::ExecutionEngine *, const char *) qv4vme_moth.cpp 766 0x1012d5c13 28 QV4::Moth::VME::exec(QV4::CppStackFrame *, QV4::ExecutionEngine *) qv4vme_moth.cpp 463 0x1012d4542 29 QV4::Function::call(QV4::Value const *, QV4::Value const *, int, QV4::ExecutionContext const *) qv4function.cpp 69 0x10127a985 30 QV4::Script::run(QV4::Value const *) qv4script.cpp 162 0x1012af6ca 31 QJSEngine::evaluate(QString const&, QString const&, int) qjsengine.cpp 545 0x101237d86 32 clsJSON::blnDecodeAccordingToType(QJsonObject const&, QTcpSocket *) clsJSON.cpp 377 0x10001859d 33 clsModule::manageReceivedData(QTcpSocket *) clsModule.cpp 230 0x100069269 34 clsServer::onReadyRead() clsListener.cpp 84 0x10001b1e1 35 QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (clsServer:: *)()>::call(void (clsServer:: *)(), clsServer *, void * *) qobjectdefs_impl.h 152 0x10001d1ab 36 void QtPrivate::FunctionPointer<void (clsServer:: *)()>::call<QtPrivate::List<>, void>(void (clsServer:: *)(), clsServer *, void * *) qobjectdefs_impl.h 185 0x10001d11d 37 QtPrivate::QSlotObject<void (clsServer:: *)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase *, QObject *, void * *, bool *) qobjectdefs_impl.h 418 0x10001d072 38 QObject::event(QEvent *) qobject.cpp 1314 0x10278bb9f 39 QApplicationPrivate::notify_helper(QObject *, QEvent *) qapplication.cpp 3632 0x100b8c9ea 40 QApplication::notify(QObject *, QEvent *) qapplication.cpp 0x100b8de11 41 QCoreApplication::notifyInternal2(QObject *, QEvent *) qcoreapplication.cpp 1063 0x102760a34 42 QCoreApplication::sendEvent(QObject *, QEvent *) qcoreapplication.cpp 1458 0x102761d79 43 QCoreApplicationPrivate::sendPostedEvents(QObject *, int, QThreadData *) qcoreapplication.cpp 1817 0x102761d64 44 QCocoaEventDispatcherPrivate::processPostedEvents() qcocoaeventdispatcher.mm 904 0x102232259 45 QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void *) qcocoaeventdispatcher.mm 927 0x1022329c8 46 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ (x86_64h) /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation 0x7ff8188138fd 47 __CFRunLoopDoSource0 (x86_64h) /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation 0x7ff818813865 48 __CFRunLoopDoSources0 (x86_64h) /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation 0x7ff8188135e4 49 __CFRunLoopRun (x86_64h) /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation 0x7ff81881201b 50 CFRunLoopRunSpecific (x86_64h) /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation 0x7ff8188115dd 51 RunCurrentEventLoopInMode (x86_64) /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox 0x7ff8214444f1 52 ReceiveNextEventCommon (x86_64) /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox 0x7ff821444247 53 _BlockUntilNextEventMatchingListInModeWithFilter (x86_64) /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox 0x7ff821443fe5 54 _DPSNextEvent (x86_64) /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit 0x7ff81b240b4c 55 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] (x86_64) /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit 0x7ff81b23f1b8 56 -[NSApplication run] (x86_64) /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit 0x7ff81b2315a9 57 QCocoaEventDispatcher::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) qcocoaeventdispatcher.mm 437 0x10223162f 58 QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) qeventloop.cpp 139 0x10275cacf 59 QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) qeventloop.cpp 232 0x10275caab 60 QCoreApplication::exec() qcoreapplication.cpp 1371 0x102761042 61 main XMLMPAM.cpp 120 0x1000d3cf4 62 start (x86_64) /usr/lib/dyld 0x1002e94fe
@SPlatten said in Adding a virtual function causes strange result...:
clsXMLnode::strGetAttribute(QString)
You should check what is happening there
-
@SPlatten said in Adding a virtual function causes strange result...:
clsXMLnode::strGetAttribute(QString)
You should check what is happening there
-
@jsulm , this is where its called:
QString clsScriptHelper::getValue(const QString& crstrID) { QString strValue; if ( crstrID.isEmpty() != true ) { clsXMLnode* pobjNode(clsXMLnode::spobjGetNodeById(crstrID)); if ( pobjNode != nullptr ) { clsXMLinterface* pobjXMLif(reinterpret_cast<clsXMLinterface*>(pobjNode)); if ( pobjXMLif != nullptr ) { strValue = pobjXMLif->strGetData(); } } } return strValue; }
The prototype for the above:
Q_INVOKABLE QString getValue(const QString& crstrID);
There is presently only one call to this, the only overridden instance is defined in the class clsQtLineEdit.
Execution stops as I stated on the line I specified in the original post, how can I see if an error or exception has occurred because it isn't obvious.
@SPlatten said in Adding a virtual function causes strange result...:
reinterpret_cast
when using virtual inheritance !?!?!?
use dynamic_cast or if QObject classes object_cast
reinterpret_cast takes the raw pointer and considers it as being of the derived type. However, because of the virtual inheritance, a slight adjustment must be done to the pointer to point to the correct method dispatch table, and that's precisely what dynamic_cast will do.
just as wrong, but probably wouldn't have resulted in a crash would be the use of static_cast.
-
@jsulm , this is where its called:
QString clsScriptHelper::getValue(const QString& crstrID) { QString strValue; if ( crstrID.isEmpty() != true ) { clsXMLnode* pobjNode(clsXMLnode::spobjGetNodeById(crstrID)); if ( pobjNode != nullptr ) { clsXMLinterface* pobjXMLif(reinterpret_cast<clsXMLinterface*>(pobjNode)); if ( pobjXMLif != nullptr ) { strValue = pobjXMLif->strGetData(); } } } return strValue; }
The prototype for the above:
Q_INVOKABLE QString getValue(const QString& crstrID);
There is presently only one call to this, the only overridden instance is defined in the class clsQtLineEdit.
Execution stops as I stated on the line I specified in the original post, how can I see if an error or exception has occurred because it isn't obvious.
This post is deleted! -
@SPlatten said in Adding a virtual function causes strange result...:
reinterpret_cast
when using virtual inheritance !?!?!?
use dynamic_cast or if QObject classes object_cast
reinterpret_cast takes the raw pointer and considers it as being of the derived type. However, because of the virtual inheritance, a slight adjustment must be done to the pointer to point to the correct method dispatch table, and that's precisely what dynamic_cast will do.
just as wrong, but probably wouldn't have resulted in a crash would be the use of static_cast.
@J-Hilk said in Adding a virtual function causes strange result...:
dynamic_cast
I've replaced reinterpret_cast with dynamic_cast, same result.
-
@SPlatten said in Adding a virtual function causes strange result...:
I didn't use the override keyword, should I?
Yes you should. To ask the compiler to check whether you're really overriding virtual method. Can help to detect bugs at compile time.
As I suggested: check what is happening in clsXMLnode::strGetAttribute(QString).
My guess is that the strGetData() method from base class is called which returns an empty string, so the code then fails later. -
@J-Hilk said in Adding a virtual function causes strange result...:
dynamic_cast
I've replaced reinterpret_cast with dynamic_cast, same result.
@SPlatten said in Adding a virtual function causes strange result...:
I've replaced reinterpret_cast with dynamic_cast, same result.
For sure not.
btw: dynamic_cast was proposed to your exact same problem some weeks ago already: https://forum.qt.io/topic/132420/how-to-access/4
-
@SPlatten said in Adding a virtual function causes strange result...:
I didn't use the override keyword, should I?
Yes you should. To ask the compiler to check whether you're really overriding virtual method. Can help to detect bugs at compile time.
As I suggested: check what is happening in clsXMLnode::strGetAttribute(QString).
My guess is that the strGetData() method from base class is called which returns an empty string, so the code then fails later. -
@SPlatten said in Adding a virtual function causes strange result...:
I've replaced reinterpret_cast with dynamic_cast, same result.
For sure not.
btw: dynamic_cast was proposed to your exact same problem some weeks ago already: https://forum.qt.io/topic/132420/how-to-access/4
@Christian-Ehrlicher That issue was resolved, this is new and dynamic_cast wasn't used to resolve the last issue, it was resolved with the suggested qobject_cast.
-
@jsulm, I have a breakpoint on the first line of the function getValue, execution doesn't get as far as the breakpoint before the issue occurs.
-
@jsulm, I have a breakpoint on the first line of the function getValue, execution doesn't get as far as the breakpoint before the issue occurs.
-
@Christian-Ehrlicher That issue was resolved, this is new and dynamic_cast wasn't used to resolve the last issue, it was resolved with the suggested qobject_cast.
@SPlatten said in Adding a virtual function causes strange result...:
it was resolved with the suggested qobject_cast.
Since your class is derived from QObject you can also use qobject_cast. Please learn the basics.
-
@SPlatten said in Adding a virtual function causes strange result...:
it was resolved with the suggested qobject_cast.
Since your class is derived from QObject you can also use qobject_cast. Please learn the basics.
@Christian-Ehrlicher , I find your additions very insulting, I’ve been coding professionally since 1986.
-
@Christian-Ehrlicher , I find your additions very insulting, I’ve been coding professionally since 1986.
@SPlatten
I'm not sure what part of your code you think is implicated. I see:1 QListData::size() const 2 QList<std::pair<QString, QString>>::length() const
and that is failing (according to your "the execution stops in qlist.h on line 115") on trying to get the length of the
QList
. InvalidQList
at that point? That is what I see? -
@Christian-Ehrlicher , I find your additions very insulting, I’ve been coding professionally since 1986.
@SPlatten said in Adding a virtual function causes strange result...:
I’ve been coding professionally since 1986.
But not with c++ (at least I hope so) - when I want to learn a new language I normally start to learn the basics. But you ignore those basics in nearly every 'problem' you have and then wonder why people complain about the lack of the basics.
-
@SPlatten said in Adding a virtual function causes strange result...:
I’ve been coding professionally since 1986.
But not with c++ (at least I hope so) - when I want to learn a new language I normally start to learn the basics. But you ignore those basics in nearly every 'problem' you have and then wonder why people complain about the lack of the basics.
@Christian-Ehrlicher that’s a huge assumption on your part.
-
@SPlatten your stack trace actually points to your
clsXMLnode
class.
clsXMLnode::strGetAttribute@J-Hilk said in Adding a virtual function causes strange result...:
@SPlatten your stack trace actually points to your clsXMLnode class.
clsXMLnode::strGetAttributeIf he
reinterpret_cast
s it's going to point to that class and method since that's what to "reinterpret" means.@SPlatten said in Adding a virtual function causes strange result...:
I've replaced reinterpret_cast with dynamic_cast, same result.
You shouldn't use
reinterpret_cast
to begin with, as it's rather apparent you don't understand the implications of it; specifically to polymorphic calls and multiple inheritance. So while @Christian-Ehrlicher may seem brusque, you should do yourself a favor and listen to the advice.As for the issue at hand, you have called
strGetAttribute
on an invalid object, I'm reasonably certain. The reasons may vary, andreinterpret_cast
ing incompatible types is one. Dangling pointers and uninitialized memory are other candidates. You need to sift through the debugger to find it. Out of curiosity where doesclsQtLayout::addButton
callclsXMLnode::strGetAttribute
and where doesclsXMLnode::setWidget
callclsQtLayout::addButton
- provide the relevant code around the calls. -
@J-Hilk said in Adding a virtual function causes strange result...:
@SPlatten your stack trace actually points to your clsXMLnode class.
clsXMLnode::strGetAttributeIf he
reinterpret_cast
s it's going to point to that class and method since that's what to "reinterpret" means.@SPlatten said in Adding a virtual function causes strange result...:
I've replaced reinterpret_cast with dynamic_cast, same result.
You shouldn't use
reinterpret_cast
to begin with, as it's rather apparent you don't understand the implications of it; specifically to polymorphic calls and multiple inheritance. So while @Christian-Ehrlicher may seem brusque, you should do yourself a favor and listen to the advice.As for the issue at hand, you have called
strGetAttribute
on an invalid object, I'm reasonably certain. The reasons may vary, andreinterpret_cast
ing incompatible types is one. Dangling pointers and uninitialized memory are other candidates. You need to sift through the debugger to find it. Out of curiosity where doesclsQtLayout::addButton
callclsXMLnode::strGetAttribute
and where doesclsXMLnode::setWidget
callclsQtLayout::addButton
- provide the relevant code around the calls.@kshegunov , using the debugger I have a break point on the last if condition below:
clsXMLinterface* pobjInterface(reinterpret_cast<clsXMLinterface*>(pobjButton)); clsXMLnode* pobjNode(nullptr); if ( pobjInterface != nullptr ) { pobjNode = pobjInterface->pobjGetNode(); } if ( pobjNode == nullptr ) { return; }
pobjButton is a pointer to an instance of my derived class clsQtRadioButton:
class clsQtRadioButton : public QRadioButton, public clsXMLinterface { Q_OBJECT
pobjNode is returned as not null, pobjGetNode:
clsXMLnode* pobjGetNode() { return mpobjNode; }
I can see in the debugger the pobjInterface looks ok and mpobjNode is correct as I have assigned a human readable description to it:
However pobjNode doesn't appear to be correct:
And then trying to call strGetAttribute fails and causes the problem, but its because pobjNode isn't correct, why ?
If I change the code to:clsQtRadioButton* pobjRadioBtn(qobject_cast<clsQtRadioButton*>(pobjButton)); clsXMLnode* pobjNode(pobjRadioBtn->pobjGetNode());
This way pobjNode is valid and there is no problem, however I need a polymorphic way to access pobjGetNode because there can be lots of different types of object derived from the same base class and I need the functionality to work for all of them.
-
@kshegunov , using the debugger I have a break point on the last if condition below:
clsXMLinterface* pobjInterface(reinterpret_cast<clsXMLinterface*>(pobjButton)); clsXMLnode* pobjNode(nullptr); if ( pobjInterface != nullptr ) { pobjNode = pobjInterface->pobjGetNode(); } if ( pobjNode == nullptr ) { return; }
pobjButton is a pointer to an instance of my derived class clsQtRadioButton:
class clsQtRadioButton : public QRadioButton, public clsXMLinterface { Q_OBJECT
pobjNode is returned as not null, pobjGetNode:
clsXMLnode* pobjGetNode() { return mpobjNode; }
I can see in the debugger the pobjInterface looks ok and mpobjNode is correct as I have assigned a human readable description to it:
However pobjNode doesn't appear to be correct:
And then trying to call strGetAttribute fails and causes the problem, but its because pobjNode isn't correct, why ?
If I change the code to:clsQtRadioButton* pobjRadioBtn(qobject_cast<clsQtRadioButton*>(pobjButton)); clsXMLnode* pobjNode(pobjRadioBtn->pobjGetNode());
This way pobjNode is valid and there is no problem, however I need a polymorphic way to access pobjGetNode because there can be lots of different types of object derived from the same base class and I need the functionality to work for all of them.
@SPlatten said in Adding a virtual function causes strange result...:
why ?
We do not know whether and how you're initialising it...
"pobjNode is returned as not null" - doesn't mean it was initialised. You should initialise your pointers with nullptr before they are assigned proper pointers, else they can contain garbage.
-
@SPlatten said in Adding a virtual function causes strange result...:
why ?
We do not know whether and how you're initialising it...
"pobjNode is returned as not null" - doesn't mean it was initialised. You should initialise your pointers with nullptr before they are assigned proper pointers, else they can contain garbage.
@jsulm , here is the constructor for the class clsXMLinterface:
clsXMLinterface::clsXMLinterface(clsXMLnode* pobjNode) : mpobjNode(pobjNode) {
And clsQtRadioButton:
clsQtRadioButton::clsQtRadioButton(clsXMLnode* pobjNode, QString* pstrCSS , QWidget* pParent) : QRadioButton(pParent), clsXMLinterface(pobjNode) {
The formatting of this constructor is common to all instances. Widgets like instances of clsQtRadioButton are created by another call:
pobjWidget = qobject_cast<QWidget*>(clsCNT::pCreate(this, mstrName, strCSS, slstProperties, pobjParWidget));
clsCNT::pCreate:
QWidget* clsCNT::pCreate(clsXMLnode* pobjNode, const QString& crstrType ,QString& rstrCSS, QStringList& rslstProperties ,QWidget* pobjParent) { QWidget* pobjWidget(nullptr); if ( pobjNode != nullptr ) { if ( crstrType.compare(clsCNT::mscszButton) == 0 ) { pobjWidget = new clsQtPushBtn(pobjNode, &rstrCSS, pobjParent);
The above is just a sample, pobjNode is passed by pCreate as this.