QTabWidget - SegFault if last tab is closed



  • Hello!
    I tried to post my problem in this thread: http://qt-project.org/forums/viewthread/27672/
    I try it now again, perhaps no one answered because of the [solved]-flag in the thread title.

    I have a custom QTabWidget (a class thats inherits from it) with tabs that hold TableViews.
    The Widget first has no Tabs, the user can add them.
    My problem now is, that i don't know how to close the LAST EXISTING (not the most right or something) tab, i.e. clear the tabWidget.
    Whenever i close the last tab (with removeTab() or by deleting the TableView pointer), the application crashes with a segfault. It does the same, of course, if I use QTabWidget.clear() at any time.
    Why is it not possible for the Widget to exist with zero tabs? It starts with zero tabs, so this shouldn't be difficult.
    I do not think I handle pointers wrong or something, because every other Tab is closed fine, if it is not the last one that exists.

    I use Win 7, Qt 4.8.4 with MinGW.
    Thank you!



  • Hi, normally, SegFault can be easily found and solved by debug your application.

    Otherwise, source code is needed if you want to get some advice form others..



  • Hello,
    I tried this, but im not that deep into debugging. If I run debug mode, the following function causes the segFault (if I understand the debug message correctly..):
    QAbstractItemView5modelEv
    I dont use custom QAbstractItemView, so I guess its not some wrong coding on this level, but a wrong usage of the TabWidget.
    I can show code, of course, but i doesn't make much sense I guess:
    @void DeviceWidget::deleteDevice(){
    QTableView temp = static_cast<QTableView>(currentWidget());
    DeviceSortModel proxy = static_cast<DeviceSortModel>(temp->model());

    delete temp;
    delete proxy;
    

    }@
    The following Code produces the same error:
    @void DeviceWidget::deleteDevice(){
    this->removeTab(this->currentIndex());
    }@
    And in addition, as I said, EVERY call of this->clear() (where "this" is inhereted from QTabWidget) causes the segFault.
    Thank you for your answer!



  • In the deleteDevice() function, you shouldn't just delete the widgets!! Always check if pointers aren't NULL. The cast will result in NULL is the cast can't be made.
    The clear() function of a QTabWidget should be handled without issues on an a filled TabWidget with no widgets on the tabs etc.
    Do you reverence the QTableView somewhere else as well?
    A bit more code to really help out. Because some part of the code crashed doesn't really mean that that rule is wrong, just the consequence of it and normally that is the place where the statement is executed ;-)


  • Moderators

    First, some good programming practices:

    • For QObjects, always use qobject_cast, not static_cast
    • For QObjects, always use deleteLater(), not delete (unless you don't have an event loop)
    • Like Jeroentje said, check your pointer before deleting

    On to your original problem:

    How does DeviceWidget::deleteDevice() get called?

    Click "Start Debugging" (the green arrow with the little beetle on top), wait till a crash, and post the stack trace (a stack trace is the list of functions that led up to the crash)



  • Hello again and thank you for your patience :)
    I tried now this:
    @void DeviceWidget::deleteDevice(){
    QTableView temp = qobject_cast<QTableView>(currentWidget());
    DeviceSortModel proxy =qobject_cast<DeviceSortModel>(temp->model());
    Device dev = qobject_cast<Device>(proxy->sourceModel());

    if(temp) temp->deleteLater();
    if(proxy) proxy->deleteLater();
    if(dev) dev->deleteLater();
    

    }@
    Still the same behaviour: Everything works fine, I can add and remove Tabs&Widgets, only the last tab causes the app to crash.
    To answer the questions:

    1. It gets called by an action from the mainwindow. Just a button, nothing special here.
      2.As I said, I tried debugging, but i dont get more information out of it then the function:
      @0 ZNK17QAbstractItemView5modelEv C:\Qt\4.8.4\bin\QtGui4.dll 0x67babf5c
      1 ?? 0x41476e
      2 ?? 0x28ce54 @
      Using Breakpoint seems senseless to me, as I know where the app crashs, but I really don't know much about debugging.

    Do you guys perhaps can explain me why the LAST EXISTING tab causes such a problem? If parenting and pointers would be wrong, the problem should occur also if I just remove one tab out of many, shouldn't it?

    Thanks again for the support, I love the framework and its community!



  • Perhaps it could sounds a stupid thing, but I would try to ensure that the pointers of the cast are not null:

    @
    QTableView temp = qobject_cast<QTableView>(currentWidget());

    if (temp))
    {
    temp->deleteLater();
    DeviceSortModel proxy =qobject_cast<DeviceSortModel>(temp->model());
    if (proxy)
    {
    proxy->deleteLater();
    Device dev = qobject_cast<Device>(proxy->sourceModel());
    if (dev)
    dev->deleteLater();
    }
    }
    @

    The segmentation fault is perfectly possible when you are doing the dev->deleteLater() or at any moment if any of the casts returns NULL.

    Despite this, could you set a breakpoint at the line
    @QTableView *temp...@
    and continuing with F10 to know in with specific line it crashes?


  • Moderators

    [quote author="Banshee" date="1373061834"]
    Do you guys perhaps can explain me why the LAST EXISTING tab causes such a problem? If parenting and pointers would be wrong, the problem should occur also if I just remove one tab out of many, shouldn't it?[/quote]
    Not that simple, unfortunately. Memory bugs can be a pain to track down.

    I've encountered strange crashes before when launching dialogs from a menu. I was never able to find the root cause, but I connected the signal from the menu using a queued connection to give other functions time to finish running first, and that made my problem go away (for now?). Try that and see if it helps, e.g.

    @
    connect(action, SIGNAL(triggered()), deviceWidget, SLOT(deleteDevice()), Qt::QueuedConnection);
    @

    It's not an ideal solution and I suspect there could be a bug in Qt, but I haven't had the time to pinpoint the cause to make a meaningful bug report.

    More questions: What version of MinGW are you using? Did it come with GDB?



  • Hi,
    please compile your application under Debug mode instead of Release mode before you try to debug it.



  • Hello,
    Thank you for your advices. I will keep them in mind:)

    Actually, I just found a workaround:
    @void MainWindow::clearDevice(){
    if(devWidg->count()>1){
    devWidg->deleteDevice();
    return;
    }

    devWidg->deleteLater();
    devWidg=new DeviceWidget(this);
    
    setUpConnectionsDevice();
    
    ui->gridLayout->addWidget( devWidg);
    

    }@

    Before I call the deleteDevice Slot, I check if there are enough tabs. If not, the whole Widget is deleted, and then re-added as it was at the start of the app.
    Not the best solution, but it works for now
    In a few days I will have the time to anaylze the problem deeper.
    Thank you!



  • place [SOLVED] in front of your first post!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.