PDA

View Full Version : App crashing on addRow to QStandardItemModel



homerun4711
28th December 2010, 14:37
Hi!

I try to add values from a map to a QStandardItemModel, but my application is crashing. I have no idea why..

The last debug output is


QStandardItemModel::invisibleRootItem() const

The code is


QMap<QString, QString> map;
QMapIterator<QString, QString> i(map);
QList<QStandardItem*> rowList;
QStandardItemModel* test;
QStandardItem *item = test->invisibleRootItem();


while (i.hasNext()) {
i.next();
rowList << new QStandardItem(i.value());
}

item->appendRow(rowList);

Can you tell me why this happens?

Kind regards,
HomeR

high_flyer
28th December 2010, 14:50
You are defining 'test' pointer, but not initializing it, but you call invisibleRootItem() on it - no wonder it crashed!


QStandardItemModel* test; //<<-- not initialized
QStandardItem *item = test->invisibleRootItem(); //crash!

homerun4711
28th December 2010, 15:03
You are right.
Sometimes I am dumb and blind :)

homerun4711
28th December 2010, 18:29
Hm, there is something else going wrong...could you please have a look into the code? I initialized the pointer but the application is still crashing at the same spot.

mainwindow.h


QStandardItemModel *model_customer;

mainwindow.cpp




MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
...
setupModels();
...
}

void MainWindow::setupModels()
{


QStandardItemModel *model_customer = new QStandardItemModel;

}

void MainWindow::newcustomer() //called with a QPushButton
{

AddressNew *newcustomer = new AddressNew(this);
if (newcustomer->exec())
{
newcustomer->addToModel(model_customer);
}

AddressNew.h


void setMap(QStandardItemModel* model);

AddressNew.cpp


void AddressNew::setMap(QStandardItemModel* model)

QMap<QString, QString> map; //contains QStrings from QLineEdits
QMapIterator<QString, QString> i(map);
QList<QStandardItem*> rowList;
QStandardItemModel* test = new QStandardItemModel;
QStandardItem *item = model->invisibleRootItem();

while (i.hasNext()) {
i.next();
rowList << new QStandardItem(i.value());
}

item->appendRow(rowList);

Any ideas?

nroberts
28th December 2010, 18:38
void AddressNew::setMap(QStandardItemModel* model)

QMap<QString, QString> map; //contains QStrings from QLineEdits
QMapIterator<QString, QString> i(map);
QList<QStandardItem*> rowList;
QStandardItemModel* test = new QStandardItemModel;
QStandardItem *item = model->invisibleRootItem();


Well, now you've changed from getting the root item from 'test' to getting it from 'model', which is a parameter; 'test' now not being used. The problem is probably in calling code, which you haven't provided. May very well be exactly the same problem as before: invalid pointer.

homerun4711
28th December 2010, 19:12
Well, I tried to add the row to the model using


model->appendRow(rowList);

instead of


item->appendRow(rowList);

but the application is crashing anyway...

I tried to stick to code I found here (see 3.1 TreeView)

http://doc.troll.no/master-snapshot/modelview.html


standardModel = new QStandardItemModel ;
QList<QStandardItem *> preparedRow =prepareRow("first", "second", "third");
QStandardItem *item = standardModel->invisibleRootItem();
// adding a row to the invisible root item produces a root element
item->appendRow(preparedRow);

nroberts
28th December 2010, 19:27
Well, I tried to add the row to the model using


model->appendRow(rowList);

instead of


item->appendRow(rowList);

but the application is crashing anyway...


Which leads me to believe I'm probably right and the problem is that 'model' is not initialized to mean anything. We can't tell for sure at this point though because the code that would be responsible for creating it, whatever is calling your AddressNew::setMap function, is not part of the code you provided in your question.

Edit:

Nevermind.... I'm wrong. You did provide that code; I just didn't see it. Your symptoms would lead me to believe I'm right but unless something is coming along and hosing your model_customer or something I'm not. You might just break in that function and make sure *model is something valid just to be sure though.

homerun4711
28th December 2010, 19:54
Ok, we are getting closer :) You are right, maybe the pointer is not
initialized when it is needed.
AddressNew::setMap is called (AddressNew is a QDialog) when the Dialog is
accepted.


AddressNew *newcustomer = new AddressNew(this);

if (newcustomer->exec())
{
newcustomer->setMap(model_customer);
}

nroberts
28th December 2010, 20:03
Ok, we are getting closer :) You are right, maybe the pointer is not
initialized when it is needed.
AddressNew::setMap is called (AddressNew is a QDialog) when the Dialog is
accepted.


AddressNew *newcustomer = new AddressNew(this);

if (newcustomer->exec())
{
newcustomer->setMap(model_customer);
}

Oh shit, I know where your problem is. Should have seen it before.

See your second cry for help post: http://www.qtcentre.org/threads/37361-App-crashing-on-addRow-to-QStandardItemModel?p=171700#post171700

In the first code segment you create an apparently global model_customer variable. Even if it's not global but is part of the class definition, the problem is still the same: name resolution applied to scoping rules.

Later, in setupModels() you do what kind of looks like an initialization of that variable, but it isn't. Because you provide the type before the variable name (QStandardItemModel*) you are actually declaring a new variable within a smaller scope, overriding the former. Thus the former, global version is never initialized and the pointer you DO initialize silently goes away, creating a memory leak BTW. Then when you call setMap you pass the former, global, uninitialized variable.

To fix your code, change this:



void MainWindow::setupModels()
{


QStandardItemModel *model_customer = new QStandardItemModel;

}

To this:



void MainWindow::setupModels()
{


model_customer = new QStandardItemModel;

}

homerun4711
28th December 2010, 21:37
Oh my god, you are SO right!!!
Thank you very much! Exactly this was the problem.
So much to learn... :)