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.
wrote on 21 Dec 2021, 14:25 last edited by@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
wrote on 21 Dec 2021, 14:31 last edited by SPlatten@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.
@SPlatten your stack trace actually points to your
clsXMLnode
class.
clsXMLnode::strGetAttribute -
@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.
@SPlatten I'm talking about clsXMLnode::strGetAttribute(QString).
If you check the stack trace you posted you will see that it is called shortly before the application stopps... -
@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.
wrote on 21 Dec 2021, 15:12 last edited by@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.
wrote on 21 Dec 2021, 15:20 last edited by JonB@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.
wrote on 21 Dec 2021, 16:06 last edited by@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.wrote on 22 Dec 2021, 07:43 last edited by SPlatten@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.
wrote on 22 Dec 2021, 07:55 last edited by SPlatten@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.
18/31