PDA

View Full Version : delete runtime-created widgets causes crash



jonasbalmer
9th February 2010, 22:32
I'm trying to dynamicly add and remove widgets to a gridlayout based on what the user selects in a combobox named EffectChoice. This works perfect if I select an effect with one argument(a new ComboBox is added) and then choose an effect with 0 arguments(the ComboBox is deleted). However, if I then select the effect with one argument again, Qt crashes at this line:
if(!ui->grdVisuals->itemAtPosition(row,x)->isEmpty()){
This is the full code of the combobox:


void MainWindow::on_EfectChoice_ValueChanged(QString Effect){
int row = QObject::sender()->property("Row").toInt(); //get the row number
for(int x=1;x<ui->grdVisuals->columnCount();x++){ //loop all the row items except the first one
if(!ui->grdVisuals->itemAtPosition(row,x)->isEmpty()){
QComboBox* cboVar = qobject_cast<QComboBox*>(ui->grdVisuals->itemAtPosition(row,x)->widget());
if(cboVar){//remove the widget
ui->grdVisuals->removeWidget(cboVar);
ui->grdVisuals->removeItem(ui->grdVisuals->itemAtPosition(row,x));
cboVar->setParent(NULL);
delete cboVar;
}
}
}
for(int i=0;i < GLOutput->VisualList.count();i++){//loop the Visuals list to retrieve effect data
if(GLOutput->VisualList.at(i).Visual == Effect){
for(int a=0; a<GLOutput->VisualList.at(i).ArgCount;a++){//create a new combobox for each argument of the effect
QComboBox* InputType = new QComboBox;
InputType->setMinimumWidth(200);
ui->grdVisuals->addWidget(InputType,row,a+1,1,1,Qt::AlignLeft);
}
}
}
}

I'd google it, but I don't really know what's causing it and what searchwords to use.

franz
9th February 2010, 22:54
Either ui, ui->grdVisuals or ui->grdVisuals->itemAtPosition(row,x) does not exist, causing an invalid memory access.

On a side note, why not use a QStackedWidget? You can just create the pages once and decide which one to show based on your combo. Much easier and less error prone if you ask me.

jonasbalmer
10th February 2010, 15:34
is there a way to test if it exists? I thought the ->isEmpty() function did that.
I don't want to use the QStackedWidget, because I want to delete the widget if I don't need it. Having all possibilities hidden in stead of deleted is a waste of resource, because the list of effects will eventually get very long.

franz
10th February 2010, 18:31
When using pointers you have to make sure stuff exists and is still in existence when you use it. Some values may be altered by other parts of your software. Make sure that if you delete a certain object, you set it's pointer to 0. That is the only reliable way to check if a value pointed at is still actually in existence.

Please post a stack trace for the crash. That might be helpful.

jonasbalmer
10th February 2010, 22:02
0 MainWindow::Idle mainwindow.cpp 109 0x000000000040b703
1 MainWindow::qt_metacall moc_mainwindow.cpp 107 0x0000000000423329
2 QMetaObject::activate(QObject*, int, int, void**) /usr/lib/libQtCore.so.4 0 0x00007ffff5322ddc
3 QObject::event(QEvent*) /usr/lib/libQtCore.so.4 0 0x00007ffff531cd83
4 QApplicationPrivate::notify_helper(QObject*, QEvent*) /usr/lib/libQtGui.so.4 0 0x00007ffff5abbefc
5 QApplication::notify(QObject*, QEvent*) /usr/lib/libQtGui.so.4 0 0x00007ffff5ac31ce
6 QCoreApplication::notifyInternal(QObject*, QEvent*) /usr/lib/libQtCore.so.4 0 0x00007ffff530dc2c
7 ?? /usr/lib/libQtCore.so.4 0 0x00007ffff5338862
8 ?? /usr/lib/libQtCore.so.4 0 0x00007ffff533625d
9 g_main_context_dispatch /lib/libglib-2.0.so.0 0 0x00007ffff2c3fbce
10 ?? /lib/libglib-2.0.so.0 0 0x00007ffff2c43598
11 g_main_context_iteration /lib/libglib-2.0.so.0 0 0x00007ffff2c436c0
12 QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) /usr/lib/libQtCore.so.4 0 0x00007ffff53361a6
13 ?? /usr/lib/libQtGui.so.4 0 0x00007ffff5b504be
14 QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) /usr/lib/libQtCore.so.4 0 0x00007ffff530c532
15 QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) /usr/lib/libQtCore.so.4 0 0x00007ffff530c904
16 QCoreApplication::exec() /usr/lib/libQtCore.so.4 0 0x00007ffff530eab9
17 main main.cpp 12 0x000000000040a6fc
this is my stack trace
By setting it's pointer to 0 do you mean something like cboVar = NULL? I used to work in visual basic, this pointer stuff is a bit new to me.
Thanks for the help so far.

franz
10th February 2010, 22:36
http://www.cplusplus.com/doc/tutorial/pointers/

You will have to check whether ui->grdVisuals->itemAtPosition(row, x) returns 0 or not. If it returns 0, there is no widget located at the given position.