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

Alles rund um die Programmierung mit Qt
Antworten
nasahl
Beiträge: 33
Registriert: 24. Juli 2008 12:30

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

Beitrag 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
Zuletzt geändert von nasahl am 22. Dezember 2008 17:01, insgesamt 1-mal geändert.
Volker
Beiträge: 343
Registriert: 30. Juni 2005 05:27

Beitrag 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.
Bitte seid so nett und ändert den Titel von Beiträgen die gelöst wurden, auf [gelöst] Beitragstitel
Undefined
Beiträge: 34
Registriert: 19. Oktober 2006 17:12

Beitrag von Undefined »

Wundert mich gar nicht - stell mal deinen Compiler richtig ein und verwende -Wall oder z.B: -Weffc++
Volker
Beiträge: 343
Registriert: 30. Juni 2005 05:27

Beitrag 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.
Dateianhänge
BugTestMini.zip
Crash Minimal Beispiel
(2.37 KiB) 225-mal heruntergeladen
Bitte seid so nett und ändert den Titel von Beiträgen die gelöst wurden, auf [gelöst] Beitragstitel
nasahl
Beiträge: 33
Registriert: 24. Juli 2008 12:30

Beitrag 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
nasahl
Beiträge: 33
Registriert: 24. Juli 2008 12:30

Beitrag 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.
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag 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?
nasahl
Beiträge: 33
Registriert: 24. Juli 2008 12:30

Beitrag 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.
Antworten