segfault in qlistwidget
-
im inheriting QListWidget to MyListWidget
why do i keep getting segfault here?
void MyListWidget::keyPressEvent(QKeyEvent *event)
{
if ( event->key() == Qt::Key_Delete )
{for ( QList<QListWidgetItem*>::iterator iter = selectedItems().begin(); iter != selectedItems().end(); iter++ ) { qDebug() << (*iter)->text(); } }
}
but when i do this, it works fine
void MyListWidget::keyPressEvent(QKeyEvent event)
{
if ( event->key() == Qt::Key_Delete )
{
QList<QListWidgetItem> sItems = selectedItems();
for ( QList<QListWidgetItem*>::iterator iter = sItems.begin(); iter != sItems.end(); iter++ )
{
qDebug() << (*iter)->text();
}}
}
-
Where exactly does it crash? in the line with qDebug()?
Try to debug and execute step by step. -
This should segfault on the qDebug line most of the time.
Your first version is using two different QList<QListWidgetItem*> arrays. The begin() and end() functions are from two different lists. The second version that works is iterating using a single list so the begin() and end() functions are both from the same list.
I am sure the contents of either list is the same but the memory addresses are not.
-
It is not the iterator that is the problem. From your example:
for ( QList<QListWidgetItem*>::iterator iter = selectedItems().begin(); iter != selectedItems().end(); iter++ ) { qDebug() << (*iter)->text(); }
The functions 'selectedItems().begin()' and 'selectedItems().end()' are the problem. Each time you call 'selectedItems()' a copy of QList<QListWidgetItem*> array is returned. Since you call it twice you have two different copies. The contents of the list may be the same but they are two different lists.
Consider this:
QString input_text(" some text for input "); QString text = input_text.simplified().trimmed().mid(1);
In order to have the second line work a QString is constructed (and destroyed) for each step as a copy constructor. The QString member 'simplfied()' returns an unnamed instance of a new copy of QString after performing whatever 'simplfied()' does. The member 'trimmed()' is then called from this new QString creating another unnamed instance which finally calls member 'mid(1)'. The final variable 'text' is assigned from the last member function of the unnamed instance of QString. If the last member was '.toInt()' it would return an integer instead (which won't compile unless the assigned variable is changed to an integer (or acceptes an integer as a constructor)).
The output from the above example is "ome text for input" if you are curious.
The member function QListWidget::selectedItems(void) might looks something like this:
QList<QListWidgetItem*> QListWidget::selectedItems(void) const { QList<QListWidgetItem*> list; list.push_back(<figure out what is selected>); return list; }
You end up calling this function twice and therefore you have two different lists as you would expect (returned values from the same function will each have a unique instance). Your loop starts on the beginning of the first list and ends on the last item of the second list. It is very likely they are not sitting next to each other in memory so after the first list is traversed you are running over unknown memory (which is where your segfault comes from).
You need to be careful about copy constructors (when they are created). For example, your 'for' loop uses the postfix operator 'iter++'. For simple variables (integers) this is not a problem but if you have a complex iterator calling the postfix version will be expensive at it creates a copy. A better form is to use the prefix operator '++iter' as no copy is created.