can't find linker symbol for virtual table for 'QAbstractItemViewPrivate' value
-
Hi everybody,
I'm facing an issue while developing my code for an user interface. I'm using Qt 4.8 on a Linux distro deployed with Yocto.
Here a really simple snippet of my code:// MyWidget.h class MyWidget : public QWidget { Q_OBJECT public: MyWidget( QWidget* parent ); ~MyWidget(); signals: void request_GoToNext( QString ); //!< Go to next panel private slots: void onNext( QModelIndex index ); private: QTableView *tableView; //!< View used to represent data list QStandardItemModel *dataModel; //!< Data model visualized by the view } // MyWidget.cpp MyWidget::MyWidget( QWidget *parent ) : QWidget(parent) { this->tableView = new QTableView(this); this->dataModel = new QStandardItemModel(); // "Fill-in" data model with the list of files in a specific directory ... connect( this->tableView, SIGNAL(clicked(QModelIndex)), this, SLOT(onNext(QModelIndex)), Qt::UniqueConnection ); } MyWidget::~MyWidget() { disconnect( this->tableView, SIGNAL(clicked(QModelIndex)), this, SLOT(onNext(QModelIndex)) ); this->dataModel->clear(); delete this->tableView; delete this->dataModel; } void MyWidget::onNext( QModelIndex index ) { emit this->request_GoToNext( this->dataModel->item(index.row(), index.column())->text() ); }
Problem has its origin when emitting signal 'request_GoToNext', that makes the application crash or the debug stop due to segmentation fault.
What I can see is that, in QtCreator, the point where the application seems to fail is in the file qabstractitemview.cpp, more specific in this function:QStyleOptionViewItemV4 QAbstractItemViewPrivate::viewOptionsV4() const { Q_Q(const QAbstractItemView); QStyleOptionViewItemV4 option = q->viewOptions(); if (wrapItemText) option.features = QStyleOptionViewItemV2::WrapText; option.locale = q->locale(); option.locale.setNumberOptions(QLocale::OmitGroupSeparator); option.widget = q; return option; }
To me it sounds really strange.
After emitting the signal, the application should delete current panel and build another one: setting some 'qDebug' calls this seems to happen, deleting current panel (and its children) and creating a new one, but the application fails before showing the new panel.
It seems like the program "exits" the slot 'onNext' after having delete everything related to MyWidget.Also, in teh Application Output of QtCreator I can read this message
can't find linker symbol for virtual table for 'QAbstractItemViewPrivate' value
NB - Observation
If I rewrite the code inside my slot in this wayvoid MyWidget::onNext( QModelIndex index ) { QObject::startTimer(1); emit this->request_GoToNext( this->dataModel->item(index.row(), index.column())->text() ); } void MyWidget::timerEvent( QTimerEvent *event ) { QObject::killeTimer( event->timerId() ); emit this->request_GoToNext( this->dataModel->item(index.row(), index.column())->text() ); }
Everything works fine! That's why it seems something related to "exit" slot call to me.
Many thanks for your help
-
After some other tests, I think I've found which is the issue and how to solve it.
Here a simplified snippet of my code, where there is a class Button used by a class Parent.
When button is clicked, it could cause a panel change, or raise a message, or do some other actions (not detailed beause not relevant to the question).What I found is in slot onClicked of class Button: entering the first if, the program emits the signal request_GoToPrev, which cause the class Panel to delete current panel (and its childs, even compirsed the Button!) and raise a new one.
But after emitting the signal and do all actions required, the program "comes back" to the point when it has emitted the signal and continue the instruction execution: when it reaches the second if it creashes because this is no more consistent.That's what it seems to be after my tests. Putting a return call just after the signal emission in the first if problem is solved.
// HEADER: Button.h class Button : public QPushButton { Q_OBJECT public: Button( QWidget *parent = 0 ); ~Button(); signals: void request_GoToPrev(); //!< Go to previous panel void request_GoToNext( QString ); //!< Go to next panel void signal_Error( int ); //!< Error code private slots: void onClicked(); private: typ_Button_tags *widgetTags; //!< Pointer to the tags structure that defines the \ref Button widget typ_Shared *privateCtx; //!< Reference to runtime application structure }; // C: Button.cpp Button::Button( QWidget *parent ) : QPushButton(parent) { // Do some settings, like: font, stylesheet, focus, size.. } Button::~Button() { } void Button::onClicked() { // Callback to be called when button clicked if( !this->widgetTags->callbackClick.isEmpty() ) { emit this->request_GoToPrev(); /* !!! ATTENTION !!! * * Here the instruction return HAS to be written, otherwise the application crashes. * In fact, when running, the signal 'request_GoToPrev' is sent, but the flow of the * process should exit the call of this slot. * Doing that, 'this' is no more consistent after having emitted the signal, so the * application face a segmentation fault. */ return; } // Message box if( !this->widgetTags->msgText.isEmpty() ) { // Do some other actions on 'this'... } } // HEADER: Panel.h class Panel : public QMainWindow { Q_OBJECT public: Panel( QWidget *parent = 0 ); private slots: void on_GoToNext(int index); void on_GoToPrevious(); void on_Error(int errId); private: Button *Btn; }; // C: Panel.h Panel::Panel( QWidget *parent ) : QMainWindow(parent) { // Do some settings: font, stylesheet, focus, size... this->Btn = new Button( this ); connect( this->Btn, SIGNAL(request_GoToPrev()), this, SLOT(on_GoToPrevious()), Qt::UniqueConnection ); // Do some actions to layout the button inside the panel } void Panel::on_GoToPrevious() { // Do some check... delete this->Btn; // Do some actions... }
-
Hi,
Can you show the related code ?
-
Sorry, I misread your original post.
Can you reproduce that with a minimal compilable example ?
By the way, what version of Qt 4.8 are you using ?
-
After some other tests, I think I've found which is the issue and how to solve it.
Here a simplified snippet of my code, where there is a class Button used by a class Parent.
When button is clicked, it could cause a panel change, or raise a message, or do some other actions (not detailed beause not relevant to the question).What I found is in slot onClicked of class Button: entering the first if, the program emits the signal request_GoToPrev, which cause the class Panel to delete current panel (and its childs, even compirsed the Button!) and raise a new one.
But after emitting the signal and do all actions required, the program "comes back" to the point when it has emitted the signal and continue the instruction execution: when it reaches the second if it creashes because this is no more consistent.That's what it seems to be after my tests. Putting a return call just after the signal emission in the first if problem is solved.
// HEADER: Button.h class Button : public QPushButton { Q_OBJECT public: Button( QWidget *parent = 0 ); ~Button(); signals: void request_GoToPrev(); //!< Go to previous panel void request_GoToNext( QString ); //!< Go to next panel void signal_Error( int ); //!< Error code private slots: void onClicked(); private: typ_Button_tags *widgetTags; //!< Pointer to the tags structure that defines the \ref Button widget typ_Shared *privateCtx; //!< Reference to runtime application structure }; // C: Button.cpp Button::Button( QWidget *parent ) : QPushButton(parent) { // Do some settings, like: font, stylesheet, focus, size.. } Button::~Button() { } void Button::onClicked() { // Callback to be called when button clicked if( !this->widgetTags->callbackClick.isEmpty() ) { emit this->request_GoToPrev(); /* !!! ATTENTION !!! * * Here the instruction return HAS to be written, otherwise the application crashes. * In fact, when running, the signal 'request_GoToPrev' is sent, but the flow of the * process should exit the call of this slot. * Doing that, 'this' is no more consistent after having emitted the signal, so the * application face a segmentation fault. */ return; } // Message box if( !this->widgetTags->msgText.isEmpty() ) { // Do some other actions on 'this'... } } // HEADER: Panel.h class Panel : public QMainWindow { Q_OBJECT public: Panel( QWidget *parent = 0 ); private slots: void on_GoToNext(int index); void on_GoToPrevious(); void on_Error(int errId); private: Button *Btn; }; // C: Panel.h Panel::Panel( QWidget *parent ) : QMainWindow(parent) { // Do some settings: font, stylesheet, focus, size... this->Btn = new Button( this ); connect( this->Btn, SIGNAL(request_GoToPrev()), this, SLOT(on_GoToPrevious()), Qt::UniqueConnection ); // Do some actions to layout the button inside the panel } void Panel::on_GoToPrevious() { // Do some check... delete this->Btn; // Do some actions... }