Seite 1 von 1

[teilw. gelöst] Absturz bei QItemSelection::indexes()

Verfasst: 19. Dezember 2008 17:00
von nasahl
Hallo,

ich bekomme unter VisualStudio 2005 einen Segmentation Fault beim folgenden Code:

Code: Alles auswählen

class MyTable : public QTableWidget
{
	Q_OBJECT				
public slots:
    void selectionChanged ( const QItemSelection & selected, const QItemSelection & deselected )
	{
		QTableWidget::selectionChanged( selected, deselected );
		QModelIndexList mList = selected.indexes();
		cout << "SELECTED: count:" << mList.size() << endl;
	}
Und zwar passiert das dann, wenn ich in der Table ein Feld selektiere:

Code: Alles auswählen

 	msvcr80d.dll!_CrtIsValidHeapPointer(const void * pUserData=0x00ca9ad8)  Line 2072	C++
 	msvcr80d.dll!_free_dbg_nolock(void * pUserData=0x00ca9ad8, int nBlockUse=1)  Line 1279 + 0x9 bytes	C++
 	msvcr80d.dll!_free_dbg(void * pUserData=0x00ca9ad8, int nBlockUse=1)  Line 1220 + 0xd bytes	C++
 	msvcr80d.dll!operator delete(void * pUserData=0x00ca9ad8)  Line 54 + 0x10 bytes	C++
 	WolfTable.exe!QModelIndex::`scalar deleting destructor'()  + 0x46 bytes	C++
 	WolfTable.exe!QList<QModelIndex>::node_destruct(QList<QModelIndex>::Node * from=0x00cbb354, QList<QModelIndex>::Node * to=0x00cbb354)  Line 343 + 0x3e bytes	C++
 	WolfTable.exe!QList<QModelIndex>::free(QListData::Data * data=0x00cbb340)  Line 537	C++
 	WolfTable.exe!QList<QModelIndex>::~QList<QModelIndex>()  Line 511	C++
>	WolfTable.exe!MyTable::selectionChanged(const QItemSelection & selected={...}, const QItemSelection & deselected={...})  Line 98 + 0xf bytes	C++
Beim Destruieren von mList gibt es einen Segmentation Fault (d.h. die Methode selectionChanged() wird vom Stack genommen). Eigentlich kann ich mir gar nicht vorstellen was da falsch sein soll.

Ist das ein QT Bug? Ich verwende die Version 4.4.0.

Christof

Verfasst: 20. Dezember 2008 22:20
von Volker
Ob es ein Qt Bug ist, bin ich mir nicht sicher, aber wie ich in diesem Thread geschrieben hat, hängt es evtl. mit deinen Compilereinstellungen zusammen.

Verfasst: 21. Dezember 2008 19:28
von Undefined
Wundert mich gar nicht - stell mal deinen Compiler richtig ein und verwende -Wall oder z.B: -Weffc++

Verfasst: 21. Dezember 2008 19:55
von Volker
Mal abgesehen davon, dass VisualStudio den Parameter -Weffc++ nicht kennt, höchstens /W4 und scheinbar auch /Wall,... wärst Du so nett zu erklären warum dich das nicht wundert? Und was genau man beim Compiler "richtig" einstellen soll? Aus den 383 Warnungen die in den Qt und STL Headern in meinem Minimaltest gefunden wurden, konnte ich auf die schnelle nicht herauslesen warum der Destructor von QModelIndexList nen Absturz verursacht.

Verfasst: 22. Dezember 2008 14:31
von nasahl
Ich habe das Projekt mit /W4 und /Wall übersetzt. Der Absturz bleibt. Die Schalter sind wohl auch nur andere Warninglevels für die Compilation.

Noch habe ich keine andere Idee für den Fehler als eine QT-Bug anzunehmen.

Christof

Verfasst: 22. Dezember 2008 16:59
von nasahl
Um das Thema abzuschliessen habe ich mir einen Workaround geschrieben der meine Bedürfnisse erfüllt.
Ich habe eine Table mit SelectionMode QAbstractItemView::ContiguousSelection.
Für diesen Fall gibt es nur einen QTableWidgetSelectionRange als Selektionsrange. Diesen kann man auch händisch ermitteln:

Code: Alles auswählen

	QTableWidgetSelectionRange getSingleSelection()
	{
		static const int sNotSelected = -1;
		int rowMax = rowCount();
		int colMax = columnCount();
		int row, col, startRow, startCol, endRow, endCol;
		startRow = startCol = endRow = endCol = sNotSelected;
		QAbstractItemModel* pModel = model();
		for (row = 0; row < rowMax; ++row)
		{
			for (col = 0; col < colMax; ++col)
			{
				QModelIndex index = pModel->index(row, col, rootIndex());
				if (selectionModel()->isSelected(index))
				{
					// Wir haben den Startpunkt des Selektionsrechtecks gefunden
					startRow = row;
					startCol = col;
					break;
				}
			}
			if (startRow > sNotSelected)
				break;
		}
		if (startRow == sNotSelected)
			return QTableWidgetSelectionRange();  // Wir haben keine Selektion gefunden !

		// Erst suchen wir der Reihe nach ...
		for (row = startRow+1; row < rowMax; ++row)
		{
			QModelIndex index = pModel->index(row, startCol, rootIndex());
			if (!selectionModel()->isSelected(index))
			{
				break;
			}
		}
		endRow = row-1;

		// ... und dann der Spalte nach
		for (col = startCol+1; col < colMax; ++col)
		{
			QModelIndex index = pModel->index(startRow, col, rootIndex());
			if (!selectionModel()->isSelected(index))
			{
				break;
			}
		}
	    endCol = col-1;


		return QTableWidgetSelectionRange(startRow, startCol, endRow, endCol);
	}
Elegant (und performant) ist das wohl nicht - aber wenigstens funktionierts.

Verfasst: 23. Dezember 2008 08:54
von pfid
Crasht QList<QTableWidgetItem *> QTableWidget::selectedItems () oder selectedIndexes () denn auch? Sonst könntest du doch auch:

Code: Alles auswählen

class MyTable : public QTableWidget
{
   Q_OBJECT            
public slots:
    void selectionChanged ( const QItemSelection & selected, const QItemSelection & deselected )
   {
      QList<QTableWidgetItem*> items = selectedItems;
      QModelIndexList mList;
      
      foreach (QTableWidgetItem item, items)
         mList << indexFromItem(item);

      cout << "SELECTED: count:" << mList.size() << endl;
      QTableWidget::selectionChanged( selected, deselected );
   } 
oder

Code: Alles auswählen

class MyTable : public QTableWidget
{
   Q_OBJECT            
public slots:
    void selectionChanged ( const QItemSelection & selected, const QItemSelection & deselected )
   {
      QModelIndexList mList = selectedIndexes();

      cout << "SELECTED: count:" << mList.size() << endl;
      QTableWidget::selectionChanged( selected, deselected );
   } 
Oder haste das schon probiert?

Verfasst: 23. Dezember 2008 10:27
von nasahl
Danke für den Hinweis. Das habe ich aber schon probiert und es crasht genauso. Intern benutzen diese Funktionen wohl die gleiche Implementierung.