PDA

View Full Version : Qt collections crash with SIGSEGV



asmfreak
3rd May 2013, 13:37
Hello!
I'm writing a class using Qt collections classes (i.e. QVector, QMultiHash, QMultiMap). The first class I tried to use was QMultiHash. After getting crash similar to described below, I tried using QMultiMap, got same crash and now tried QVector class.

Back to subject. The class i'm writing looks like this:


//graph.h
class Graph :public QObject, public QGraphicsItemGroup
{
Q_OBJECT
QVector< QVector <Node*> > nodes;
public:
Graph(QObject* parent=0);
~Graph();
signals:
void maxLevel(int);
public slots:
Node* addNode(const int level=0);
private slots:
void removeNode(QObject *arg);
private:
void calculateGeometry();
};

And the crash happens in this function.

//graph.cpp
Node* Graph::addNode(const int level)
{
Node* ret=NULL;
if(level<0||level>nodes.count())return ret; //crash here
if(level==nodes.count()) nodes.insert(level,QVector<Node*>());
Node* node=new Node();
ret=node;
node->setText(trUtf8("Level %1").arg(level));
connect(node,SIGNAL(destroyed(QObject*)),this,SLOT (removeNode(QObject*)));
addToGroup(node);
nodes[level].append(node);
calculateGeometry();
emit maxLevel(nodes.count());
return ret;
}

A pointer to an object of this class is used inside of a class, derived from QMainWindow.
Being called from it's constructor it works just fine.

MainWindow::MainWindow(QWidget *parent):
QMainWindow(parent),
ui(new Ui::MainWindow)
{
//........
Graph* g=new Graph();
g->addNode();
//........
}
But when addNode() is called later (not inside constructor, via signal/slot) it crashes on the string I specified. In debug mode it stops on this line inside QVector:

//qvector.h
//........
inline int count() const { return d->size; }
//........


As I said, the same thing happened with QMultiHash and QMultiMap. I'm using Qt 4.8.1 with QtCreator 2.4.1 under Linux Mint 13 (Maya) 64 bit (kernel 3.2.0-23-generic.

Is this an issue of my code or Qt? (I tend to think that this is my code's fault, but I can't find source of the problem. Please help! BTW, The code provided compiles without a single error.

ChrisW67
3rd May 2013, 22:58
The indicated line cannot crash. The call to Vector::count() is effectively a one-liner returning an int member variable. If this were broken Qt would be fundamentally unable to start: QVector is used widely.

Run a debug build of your program in your debugger. When it crashes copy and paste the stack backtrace and the value of the pointer you are calling add Node() through and post them here. My guess is that you are trying to access addNode() through a null or invalid pointer to Graph.

asmfreak
3rd May 2013, 23:48
the first call to addNode() fuction from MainWindow's constructor:

0 Graph::addNode graph.cpp 43 0x4100b8
1 MainWindow::MainWindow mainwindow.cpp 28 0x407894
2 main main.cpp 7 0x4074de

A line before crash:

level 0 int
node 29 @0x1d Node
ret 0x0 Node *
this 4271749 @0x412e85 Graph
QObject QObject
[vptr] 1142560928759121224
d_ptr @0x894cfa894c00401f QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData>>
QGraphicsItemGroup QGraphicsItemGroup
QGraphicsItem QGraphicsItem
[vptr] 15858580846535066870
d_ptr @0x75eb394801c38348 QScopedPointer<QGraphicsItemPrivate, QScopedPointerDeleter<QGraphicsItemPrivate>>
nodes <unavailable synchronous data> QVector<QVector<Node*>>
And crash. QtCreator shows a message with "App is stopped due to system message. SIGSEGV Sigmentation fault."

0 QVector<QVector<Node*> >::count qvector.h 259 0x41066f
1 Graph::addNode graph.cpp 33 0x40fef4
2 MainWindow::addNode mainwindow.cpp 197 0x4098db
3 MainWindow::qt_static_metacall moc_mainwindow.cpp 124 0x411f6d
4 QMetaObject::activate qobject.cpp 3547 0x7ffff6dc9281
5 QAbstractButton::clicked moc_qabstractbutton.cpp 220 0x7ffff7967c72
6 QAbstractButtonPrivate::emitClicked qabstractbutton.cpp 548 0x7ffff76a5a4e
7 QAbstractButtonPrivate::click qabstractbutton.cpp 541 0x7ffff76a6d8b
8 QAbstractButton::mouseReleaseEvent qabstractbutton.cpp 1123 0x7ffff76a6ffc
9 QWidget::event qwidget.cpp 8362 0x7ffff7328144
10 notify_helper qapplication.cpp 4559 0x7ffff72d7894
11 QApplicationPrivate::notify_helper qapplication.cpp 4531 0x7ffff72d7894
12 QApplication::notify qapplication.cpp 4102 0x7ffff72dd0bf
13 QCoreApplication::notifyInternal qcoreapplication.cpp 876 0x7ffff6db4e9c
14 sendEvent qcoreapplication.h 231 0x7ffff72d8862
15 QApplicationPrivate::sendMouseEvent qapplication.cpp 3170 0x7ffff72d8862
16 QETWidget::translateMouseEvent qapplication_x11.cpp 4617 0x7ffff7357bf5
17 QApplication::x11ProcessEvent qapplication_x11.cpp 3732 0x7ffff7356bae
18 x11EventSourceDispatch qguieventdispatcher_glib.cpp 146 0x7ffff73800d2
19 g_main_context_dispatch /lib/x86_64-linux-gnu/libglib-2.0.so.0 0 0x7ffff5750d53
20 ?? /lib/x86_64-linux-gnu/libglib-2.0.so.0 0 0x7ffff57510a0
... <Более>

Added this.d to watch window:


this.d QVectorData
alloc int
capacity <unavailable synchronous data>
ref <unavailable synchronous data> QBasicAtomicInt
reserved <unavailable synchronous data>
sharable <unavailable synchronous data>
size int

One thing I can say for sure - I'm not doing anything with Graph* variable except calling deleteLater() on it in destructor of MainWindow.

UPD: I tried using that QVector in other fuctions. It works cool. The only function that seem to work falsely is addNode().

amleto
4th May 2013, 12:05
How many Qt installs do you have? Are you mixing release and debug libraries? Please show compiler & linker output to confirm what you say.

Thanks

asmfreak
4th May 2013, 13:22
I guess that I need to send all of the sources.
In this ->9017<- archive files:
1) build.log - log from QtCreator after rebuild
2) 'dpkg-query --list | grep qt4.log' - log from console from dpkg.
everything else - sources.

Thanks in advance.

amleto
4th May 2013, 14:32
look at how you set up (or rather do not setup) MainWindow::g



#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGraphicsScene>
#include "graph.h"
#include "node.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT
QStateMachine *saveStates;
QGraphicsScene* scene;
Graph* g; ///////////
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

private:
Ui::MainWindow *ui;

void createStates();
void createDialogs();
signals:
void accept_file();
void accept_save();
// <SNIP>
};

#endif // MAINWINDOW_H




#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
scene=new QGraphicsScene();
Graph* g=new Graph; /////////// really?
g->setPos(0,0);
g->getGeometry();
scene->addItem(g);
Node* node=new Node;
node->setPos(20,20);
scene->addItem(node);
node=new Node;
node->setPos(80,80);
scene->addItem(node);
node=new Node;
node->setPos(180,180);
scene->addItem(node);
ui->graphicsView->setScene(scene);
connect(ui->horizontalSlider,SIGNAL(valueChanged(int)),this,SL OT(setScale(int)));
ui->horizontalSlider->setValue(75);
connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(adNode()));
connect(g,SIGNAL(maxLevel(int)),this,SLOT(setMaxDi al(int)));
Node* test=g->addNode(0);
g->addNode(0);
g->addNode(1);
g->addNode(2);
saveStates=new QStateMachine;
this->createStates();
}

void MainWindow::adNode()
{
this->g->addNode(ui->dial->value()); ////// oops!
}

asmfreak
4th May 2013, 14:48
Oh, what an idiot I am!
Thank you for your help!!
I guess this thread can be closed, since the problem is solved.

ChrisW67
4th May 2013, 22:42
I missed it in your code too.

I always add member variables, particularly pointers, to the class initialiser list at the same time as I add them to the declaration. If your code had read:


MainWindow(QWidget *p = 0): g(0) { ... }

Then the invalid pointer would have been more obvious both as a 0x0 value in the debugger and, depending on compiler/toolchain, a more specific message when it crashed. Uninitialised it contains whatever garbage is in the memory and is far harder to see that it is not valid.


// or this
MainWindow(QWidget *p = 0): g(new Graph(this)) { ... }

This provides a valid initial value and would have removed the need for the initialisation that tripped you up.