Results 1 to 20 of 20

Thread: QTableWidget Crash in Destructor

  1. #1
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Question QTableWidget Crash in Destructor

    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 

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTableWidget Crash in Destructor

    Can we see the backtrace/callstack from the debugger when the crash occurs?

  3. #3
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTableWidget Crash in Destructor

    My QDialog class is Net2Detect and is called from MainWin::versionModeSwitch()

    MS Visual Studio Call Stack:
    Qt Code:
    1. QtGuid4.dll!QTableModel::clearContents() Line 753 + 0x2a bytes
    2. QtGuid4.dll!QTableModel::clear() Line 746
    3. QtGuid4.dll!QTableModel::~QTableModel() Line 40
    4. QtGuid4.dll!QTableModel::'scaler deleting destructor'() + 0xf bytes
    5. QtCored4.dll!QObjectPrivate::deleteChildren() Line 1910 + 0x24 bytes
    6. QtGuid4.dll!QWidget::~QWidget() Line 1184
    7. QtGuid4.dll!QFrame::~QFrame() Line 227 + 0x8 bytes
    8. QtGuid4.dll!QAbstractScrollArea::~QAbstractScrollArea() Line 452 + 0xf bytes
    9. QtGuid4.dll!QAbstractItemView::~QAbstractItemView() Line 466 + 0x8 bytes
    10. QtGuid4.dll!QTableView::~QTableView() Line 481 + 0x8 bytes
    11. QtGuid4.dll!QTableWidget::~QTableWidget() Line 1849 + 0x8 bytes
    12. GCE.exe!Net2Detect::~Net2Detect() + 0x48 bytes
    13. GCE.exe!MainWin::versionModeSwitch() Line2386 0xf bytes
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. void QTableModel::clearContents()
    2. {
    3. for (int i = 0; i < tableItems.count(); ++i) {
    4. if (tableItems.at(i)) {
    5. tableItems.at(i)->view = 0;
    6. delete tableItems.at(i); // <-- crashes here
    7. tableItems[i] = 0;
    8. }
    9. }
    10. reset();
    11. }
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTableWidget Crash in Destructor

    Are you using some special kinds of items or deleting items yourself? What does versionModeSwitch() do?

  5. #5
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTableWidget Crash in Destructor

    I'm not using any special items or deleting any Qt objects myself. My table cell class only centers text, otherwise it's a generic QTableWidgetItem. Also, whether I include my '<' operator for sorting or not, I still crash in the same place.

    Qt Code:
    1. class Net2TableCell : public QTableWidgetItem
    2. {
    3. public:
    4. Net2TableCell( const QString& text, int type = NET2_TABLECELL_TYPE ) : QTableWidgetItem( text, type )
    5. {
    6. setTextAlignment( Qt::AlignCenter );
    7. }
    8.  
    9. // For sorting non-alpha table columns (IP Address & case insensitive name).
    10. bool operator<( const QTableWidgetItem& item ) const;
    11. };
    12.  
    13. bool Net2TableCell::operator<( const QTableWidgetItem& item ) const
    14. {
    15. bool bReturn = false;
    16.  
    17. switch ( this->column() )
    18. {
    19. case COL1_Name:
    20. if ( !this->text().isNull() && !item.text().isNull() &&
    21. this->text().compare( item.text(), Qt::CaseInsensitive ) < 0 )
    22. bReturn = true;
    23. break;
    24. case COL2_IP:
    25. {
    26. if ( CIPAddr::StringToAddr( this->text().toAscii() ).GetV4Address() <
    27. CIPAddr::StringToAddr( item.text().toAscii() ).GetV4Address() )
    28. bReturn = true;
    29.  
    30. break;
    31. }
    32. default:
    33. bReturn = QTableWidgetItem::operator <( item );
    34. }
    35.  
    36. return bReturn;
    37. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. void MainWin::versionModeSwitch( void )
    2. {
    3. IPv4* pNetIPList = new IPv4[ m_pController->m_nSelectedIfaces ];
    4. if ( pNetIPList == NULL )
    5. return;
    6.  
    7. for ( int i = 0; i < m_pController->m_nSelectedIfaces; i++ )
    8. pNetIPList[i] = CIPAddr::StringToAddr( m_pController->m_sCurrNetIPLst.at( i ).toAscii() ).GetV4Address();
    9.  
    10. // Create the lists in advance (from the Online table)
    11. QStringList sNameLst, sTypeLst, sIPLst, sVerLst, sCIDLst;
    12.  
    13. // Disable sorting while the table is populated, otherwise sorting
    14. // may interfere with the insertion order.
    15. m_pAllOlnTable->setSortingEnabled( false );
    16.  
    17. for ( int i = 0; i < m_pAllOlnTable->rowCount(); i++ )
    18. {
    19. if ( !m_pAllOlnTable->item( i, COL_Status )->text().compare( OLN_ONLINE ) )
    20. {
    21. sNameLst.append( m_pAllOlnTable->item( i, COL_Name )->text() );
    22. sTypeLst.append( m_pAllOlnTable->item( i, COL_DevType )->text() );
    23. sIPLst.append( m_pAllOlnTable->item( i, COL_IPAddr )->text() );
    24. sVerLst.append( m_pAllOlnTable->GetSWVer( i ) );
    25. sCIDLst.append( m_pAllOlnTable->item( i, COL_CID )->text() );
    26. }
    27. }
    28.  
    29. m_pAllOlnTable->setSortingEnabled( true );
    30.  
    31. // Display all ACN and Net2 devices
    32. Net2Detect verModeSwitchDlg( this );
    33. verModeSwitchDlg.Initialize( sNameLst, sTypeLst, sIPLst, sVerLst, sCIDLst,
    34. pNetIPList, m_pController->m_nSelectedIfaces );
    35. verModeSwitchDlg.exec();
    36.  
    37. if ( pNetIPList != NULL )
    38. delete [] pNetIPList;
    39. }
    To copy to clipboard, switch view to plain text mode 

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTableWidget Crash in Destructor

    What is the base type of pNetIPList? What happens if you comment out lines 37 and 38 in the above code?

  7. #7
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTableWidget Crash in Destructor

    Quote Originally Posted by wysota View Post
    What is the base type of pNetIPList?
    typedef unsigned long IPv4;

    Quote Originally Posted by wysota View Post
    What happens if you comment out lines 37 and 38 in the above code?
    Commenting out these lines has no effect on the crash in QTableModel::clearContents().

  8. #8
    Join Date
    Apr 2006
    Location
    Denmark / Norway
    Posts
    67
    Thanks
    3
    Thanked 12 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Windows

    Default Re: QTableWidget Crash in Destructor

    Quote Originally Posted by mclark View Post
    Qt Code:
    1. void QTableModel::clearContents()
    2. {
    3. for (int i = 0; i < tableItems.count(); ++i) {
    4. if (tableItems.at(i)) {
    5. tableItems.at(i)->view = 0;
    6. delete tableItems.at(i); // <-- crashes here
    7. tableItems[i] = 0;
    8. }
    9. }
    10. reset();
    11. }
    To copy to clipboard, switch view to plain text mode 
    As far as I can see you are deleting a an item in a table while working on it. Which then would reindex the item (if i'm not mistaken...), making the count all different. If your count gives you 3, and you delete 1 item, i will still end up at 3, where it crashes, because 3 is now really at index 2...?

    Make a QList over the items you want to delete, then go through the list and delete the items.

    Qt Code:
    1. void QTableModel::clearContents()
    2. {
    3. QList <int> deletelist;
    4. // changed to i++, as you probably want to look at item on pos 0 as well?
    5. for (int i = 0; i < tableItems.count(); i++) {
    6. if (tableItems.at(i)) {
    7. tableItems.at(i)->view = 0;
    8. deletelist.append(i);
    9. tableItems[i] = 0;
    10. }
    11. }
    12. if (deletelist.isEmpty() == false)
    13. {
    14. for (int i = 0; i< deletelist.count(); i++)
    15. {
    16. delete tableItems.at(deletelist[i]);
    17. }
    18. }
    19. reset();
    20. }
    To copy to clipboard, switch view to plain text mode 

  9. #9
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTableWidget Crash in Destructor

    Quote Originally Posted by luf View Post
    As far as I can see you are deleting a an item in a table while working on it...
    The code for clearContents() is Qt code, nothing I have control over. My debugger kindly shows me where the problem is, and this is always the culprit.

    The table in the dialog is stable (any sorting completed) and the cancel button pressed. This leads to the dialog, widget, view ... destructors being called, eventually crashing in clearContents().

  10. #10
    Join Date
    Apr 2006
    Location
    Denmark / Norway
    Posts
    67
    Thanks
    3
    Thanked 12 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Windows

    Default Re: QTableWidget Crash in Destructor

    Hi

    Sorry, my bad! I thought you had made your own subclass...

    Leif

  11. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTableWidget Crash in Destructor

    Are you creating any of the widgets or items on the stack?

  12. #12
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTableWidget Crash in Destructor

    Quote Originally Posted by wysota View Post
    Are you creating any of the widgets or items on the stack?
    QTableWidget:
    Qt Code:
    1. m_pNodeTable = new QTableWidget( 0, 6, this );
    To copy to clipboard, switch view to plain text mode 

    QTableWidgetItems:
    Qt Code:
    1. QString sName( "" );
    2. if ( !pNotify->name.empty() )
    3. sName.sprintf( "%s", pNotify->name.c_str() );
    4. Net2TableCell* pCell = new Net2TableCell( sName );
    To copy to clipboard, switch view to plain text mode 

    All buttons are part of the Qt Designer *.ui file.

    It's a fairly simple implementation that I've used elsewhere in the application. The difference is that here I can get notifications (that cause a row insertion) at anytime.

  13. #13
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: QTableWidget Crash in Destructor

    Do you have spans in the table?
    J-P Nurmi

  14. #14
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTableWidget Crash in Destructor

    Quote Originally Posted by jpn View Post
    Do you have spans in the table?
    No spans; 6 cells containing only text.

  15. #15
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTableWidget Crash in Destructor

    What prevents Qt from sorting during inserts (please read the full message before answering)?

    Does the following sound plausible?
    1. A user presses a QTableWidget column header to initiate a sort of 215 rows of 6 cells each (1290 items).
    2. I receive a notification to add a row and disable sorting BEFORE Qt has finished the previous sort.
    If Qt is not done sorting when I disable sorting and start adding row items, could the item pointers become confused and account for the problems outlined above?

  16. #16
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTableWidget Crash in Destructor

    Can (2) happen from within the sort() method of the proxy or the base model? Remember that sorting is synchronous, so unless you provided your own implementation of sort(), the answer will be "no". If you are using multiple threads, then you shouldn't be accessing the same QObject from more than one thread.

  17. #17
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTableWidget Crash in Destructor

    This one appears unsolvable so I'll just have to change my design. I'll collect all notifications in the main app. When the dialog is constructed, the table will only contain a snapshot of devices known at the time of dialog instantiation.

    The table in the dialog will not be updated dynamically. Not a big deal but the original problem still irritates...

    Thanks to all who tried to help!

  18. #18
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTableWidget Crash in Destructor

    But do you use more than one thread in your application?

  19. #19
    Join Date
    Aug 2006
    Location
    Madison, WI USA
    Posts
    153
    Thanks
    35
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTableWidget Crash in Destructor

    Quote Originally Posted by wysota View Post
    But do you use more than one thread in your application?
    Yes, multiple threads are running in the app. In the offending dialog, a notification thread was running. The notification handler was locked using a QMutexLocker, where the mutex was declared as a class member. This should protect the table insertion code, no?
    Qt Code:
    1. QMutexLocker locker( &m_NotifyMutex );
    To copy to clipboard, switch view to plain text mode 

  20. #20
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTableWidget Crash in Destructor

    You can't access QObjects from more than one thread and no mutex will help here. You have to make sure that you follow that rule.

Similar Threads

  1. Confused - QGraphicsItem destructor
    By durbrak in forum Qt Programming
    Replies: 7
    Last Post: 13th February 2008, 20:27
  2. Crash in QTableWidget
    By ghorwin in forum Qt Programming
    Replies: 3
    Last Post: 29th October 2007, 16:57
  3. Crash on QString Destructor
    By ToddAtWSU in forum Qt Programming
    Replies: 1
    Last Post: 14th June 2007, 14:28
  4. QList crash in destructor
    By mclark in forum Newbie
    Replies: 7
    Last Post: 6th December 2006, 15:27

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.