I’m seeing a crash in my QTableWidget destructor when QTableModel::clearContents() is called. It is trying to delete memory (0xfeeefeee) that has already been deleted.

I have a dialog containing a QTableWidget that I partially fill with about 190 rows (6 columns, all text). I then start a notification service which will notify me when a particular device is discovered on the network. As part of handling a notification I insert another row into the table and fill it. My test case has about 14 notifications.

If, during the notifications, the table is sorted, a crash may happen when closing the dialog. I place setSortingEnabled() calls around the notification handler but to no avail. If no sorting occurs during notifications, all is fine.

What appears to be happening is that the table is sorting while QTableWidgetItems are being added during the notification handling. This leads to duplication of QTableWidget pointers, which causes the ‘deletion of table items already deleted’ problem.

Has anyone experienced this before? Am I being a dolt and forgetting to do something obvious?

MS Visual Studio 2005
Qt 4.3.4 commercial

Qt Code:
  1. void Net2Detect::Online( const notifystruct* pNotify )
  2. {
  3. // The mutex will always be unlocked when the QMutexLocker object is
  4. // destroyed (when the function returns since locker is an auto variable)
  5. QMutexLocker locker( &m_NotifyMutex );
  6.  
  7. if ( !m_bNotifierStarted )
  8. return;
  9.  
  10. QString sType( "" );
  11. if ( !pNotify->type.empty() )
  12. sType.sprintf( "%s", pNotify->type.c_str() );
  13.  
  14. if ( (sType != sDevice1) && (sType != sDevice2) && (sType != sDevice3))
  15. return;
  16.  
  17. m_pNodeTable->setSortingEnabled( false );
  18. Net2Notify( pNotify );
  19. m_pNodeTable->setSortingEnabled( true );
  20. }
  21.  
  22. void Net2Detect::Net2Notify( const notifystruct* pNotify )
  23. {
  24. CIPAddr addr;
  25. addr.SetV4Address( pNotify->addr );
  26. char str[CIPAddr::ADDRSTRINGBYTES];
  27. CIPAddr::AddrIntoString( addr, str, false, false );
  28. QString sIP( reinterpret_cast<const char*>(str) );
  29.  
  30. int nRow = m_pNodeTable->rowCount();
  31.  
  32. m_pNodeTable->insertRow( nRow ); // Add a row to the table
  33.  
  34. // Fill in Mode
  35. Net2TableCell* pCell = new Net2TableCell( "Net2" );
  36. if ( pCell == NULL )
  37. return;
  38.  
  39. m_pNodeTable->setItem( nRow, COL0_Mode, pCell );
  40.  
  41. // Fill in Name
  42. QString sName( "" );
  43. if ( !pNotify->name.empty() )
  44. sName.sprintf( "%s", pNotify->name.c_str() );
  45.  
  46. if ( (pCell = new Net2TableCell( sName )) == NULL )
  47. return;
  48.  
  49. m_pNodeTable->setItem( nRow, COL1_Name, pCell );
  50.  
  51. .
  52. .
  53. .
  54.  
  55. // Set the table cells as read-only
  56. Qt::ItemFlags flags = m_pNodeTable->item( nRow, COL0_Mode )->flags();
  57. flags ^= Qt::ItemIsEditable;
  58. m_pNodeTable->item( nRow, COL0_Mode )->setFlags( flags );
  59. m_pNodeTable->item( nRow, COL1_Name )->setFlags( flags );
  60. m_pNodeTable->item( nRow, COL2_IP )->setFlags( flags );
  61. m_pNodeTable->item( nRow, COL3_Type )->setFlags( flags );
  62. m_pNodeTable->item( nRow, COL4_Ver )->setFlags( flags );
  63. m_pNodeTable->item( nRow, COL5_CID )->setFlags( flags );
  64. }
To copy to clipboard, switch view to plain text mode