PDA

View Full Version : Connect call causes a SEGFAULT



Caolan O'Domhnaill
24th October 2015, 00:47
Hey all,

The code compiles and links w/o issue.
Here's where I make the connect() call in my MainWindow class. It happens in the initialisation code of my Main Window. I have verified that the source and target of signal and slot respectively are valid addresses and being created.

This yields the segfault


void CMainWindow::createSignalSlots() {
connect(m_pGraphWidget, SIGNAL(createObj(QGraphicsItem *)), m_pPhysObjNavigator, SLOT(onCreateObj(QGraphicsItem *)));
}


m_pGraphWidget is defined by the class definition like so:

class GraphWidget : public QGraphicsView {
Q_OBJECT
signals:
void createObj(QGraphicsItem *);
void removeObj(QGraphicsItem *);
void modifyObj(QGraphicsItem *);

m_pPhysObjNavigator is defined by the class definition like so:

class PhysObjectNavigator : public QTreeView {
public:
PhysObjectNavigator(QWidget * = NULL);

public slots:
void onCreateObj(QGraphicsItem *);

Code in GraphWidget that makes the emit call is here:

void GraphWidget::createCartesianGraph() {

// Create the object
m_pCartGraph = new CartesianGraph(this);
m_pCartGraph -> setPos(0, 0);
m_pScene -> addItem(m_pCartGraph);
emit createObj(m_pCartGraph);
}

Code that is supposed to receive the signal is:

void PhysObjectNavigator::onCreateObj(QGraphicsItem *pObj) {
if (pObj) {
switch (pObj -> type()) {
case PhysBaseItem::VectorType:
break;
case PhysBaseItem::ParticleType:
break;
case PhysBaseItem::CartesianGraphType:
break;
default:
break;
}
}
}
I thought it might be because PhysObjectNavigator does not have the Q_OBJECT macro defined in it but when I do put it there I get the error:
undefined reference to 'vtable for PhysObjectNavigator'
However it is derived from QTreeView which already includes Q_OBJECT so it shouldn't be a big deal.

Any ideas? It all seems set up and ready to go.

Radek
24th October 2015, 06:22
IMO, PhysObjectNavigator must be a Q_OBJECT. It does not matter that QTreeView is. Place Q_OBJECT in the PhysObjectNavigator, delete both debug and release dirs in your project and compile from scratch. The error can result from make logic.

anda_skoa
24th October 2015, 09:45
I thought it might be because PhysObjectNavigator does not have the Q_OBJECT macro defined in it but when I do put it there I get the error:
undefined reference to 'vtable for PhysObjectNavigator'

You need to re-run qmake.

The earlier run of qmake did not see the Q_OBJECT macro in the header for that class.
So it did not add the rules for MOC for that header.
So the code that MOC generates for Q_OBJECT is now missing.

Another run of qmake will add these rules.



However it is derived from QTreeView which already includes Q_OBJECT so it shouldn't be a big deal.

You added new slots in your subclass.
These need to be made known to the signal/slot system (*). Q_OBJECT or rather the MOC run processing the class, does that.

Cheers,
_

(*) for use with the SLOT() macro.
Would already work with the member function pointer connect() variant introduced in Qt5

Caolan O'Domhnaill
26th October 2015, 23:54
You need to re-run qmake.

The earlier run of qmake did not see the Q_OBJECT macro in the header for that class.
So it did not add the rules for MOC for that header.
So the code that MOC generates for Q_OBJECT is now missing.

Another run of qmake will add these rules.


You added new slots in your subclass.
These need to be made known to the signal/slot system (*). Q_OBJECT or rather the MOC run processing the class, does that.

Cheers,
_

(*) for use with the SLOT() macro.
Would already work with the member function pointer connect() variant introduced in Qt5


I have added the Q_OBJECT to the View classes I am working with. I re-executed qmake and recompiled. I no longer get the error undefined reference to 'vtable for PhysObjectNavigator' on anything however I still get the SEGFAULT in the connect call.

anda_skoa
27th October 2015, 07:25
Are both pointers valid?

If you have not done so already, initialize both pointers to 0 in CMainWindow's constructor. It is easier to spot a null pointer than an invalid pointer.

Cheers,
_

Radek
27th October 2015, 08:03
More in detail:
(1) compile for debugging.
(2) run and see that you get the segfault.
(3) put break on the suspected connect()
(4) put break at the beginning of the onCreateObj() handler
(5) debug
(6) check the values of m_pGraphWidget and m_pPhysObjNavigator at the connect(). If you pass and get into the handler
(7) check the value of pobj

Post your findings

Caolan O'Domhnaill
27th October 2015, 17:23
I actually figured it out... What you stated for the steps is what I ended up doing (w/o) breakpoints in onCreateObj() and I made a rookie mistake: I didn't initialise my pointers in the ctor of the CMainWindow. If I had, i would have seen that my main widget was being created AFTER the CMainWindow class in main(). What clued me in to this was that the address it had was not the in the same address range that the application allocated for itself for the other objects. And when I cracked it open in the debugger none of its member pointers were valid addys as well.

I am embarrassed by this as I should know better.

Cheers!
-Caolan.