Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Problem with QTabWidget::addTab() ?



  • Hi, I'm trying to add a tab inside a QTabWidget using the code below:
    @
    void test_addtab(QTabWidget parent, QString tabname){
    QWidget
    newtab = new QWidget(parent);
    parent->addTab(newtab, tabname);
    }@

    but this code was causing a program crash, so how to solve the problem? thanks.



  • Is parent eventually 0?



  • no, the parent is a QTabWidget that is valid(I tested that by myself through outputting its objectName() into a QMessageBox()).


  • Lifetime Qt Champion

    Hi,

    What does a run using the debugger tells you about the crash ?



  • I got exception at 0x67b05545, code: 0xc0000005: read access violation at: 0x0, flags=0x0:

    QtGui4!ZN14QStackedWidget12insertWidgetEiP7QWidget:
    0x67b0553c <+0x0000> push ebp
    0x67b0553d <+0x0001> mov ebp,esp
    0x67b0553f <+0x0003> sub esp,8
    0x67b05542 <+0x0006> mov eax,dword ptr [ebp+8]
    here: 0x67b05545 <+0x0009> mov eax,dword ptr [eax+4]


  • Lifetime Qt Champion

    So you are indeed accessing something that's not pointing to the right place.

    Where do you check that parent is valid ?



  • I'm sure that the parent is valid, I've just tested now this code:
    @QMessageBox::information(0,0,tabrecapTab->objectName());
    test_addtab(tabrecapTab, "test");@
    when this code was executed: a messagebox containing the parent objectName was shown, but just after that the program crashs, but when removing the line of @test_addtab(tabrecapTab, "test");@ there is no crash.



  • How where and how is tabrecapTab created? Any chance it is dangling?

    Anyway, just to be sure, edit your code like this:
    @void test_addtab(QTabWidget parent, QString tabname)
    {
    if(parent)
    {
    QWidget
    newtab = new QWidget(parent);
    parent->addTab(newtab, tabname);
    }
    else
    {
    qWarning("Parent is NULL !!!");
    }
    }@



  • [quote author="MuldeR" date="1398632164"]How where and how is tabrecapTab created? Any chance it is dangling?

    Anyway, just to be sure, edit your code like this:
    @void test_addtab(QTabWidget parent, QString tabname)
    {
    if(parent)
    {
    QWidget
    newtab = new QWidget(parent);
    parent->addTab(newtab, tabname);
    }
    else
    {
    qWarning("Parent is NULL !!!");
    }
    }@[/quote]
    it's created using the ui designer, not programmatically.
    I tested if the parent is null, and I'm sure that isn't.



  • [quote author="SGaist" date="1398631643"]So you are indeed accessing something that's not pointing to the right place.

    Where do you check that parent is valid ?[/quote]

    I"ve tested if the parent was really null using the code below:

    @ if (!tabrecapTab) QMessageBox::information(0,0,"invalid parent");
    test_addtab(tabrecapTab, "test");@
    but when the program runs: no "invalid parent" message was shown.
    so I'm sure that the parent is not null.



  • [quote author="kaisbs" date="1398632357"]
    I tested if the parent is null, and I'm sure that isn't.[/quote]

    It still doesn't hurt to make your function safe for NULL pointers.

    Anyway, even a non-NULL pointer is not guaranteed to (still) be valid:

    http://en.wikipedia.org/wiki/Dangling_pointer

    __

    Also you should make a Debug build. When it crashes, find out where exactly in the code it crashes and why. Otherwise everything is speculation.



  • I understand now the cause of this crash: because the parent is QWidget that doesn't have the addTab method, and that I've used as @QTabWidget*@ by getting it via @getChild@ then casting it to @QTabWidget*@,
    that was completely wrong, so my advice is : "never get widgets using getChild, instead use ui->widget".
    I still have to tell you now: thank you so much for your appreciated help!



  • Glad you fixed the problem.

    Side note: If you ever have to cast a pointer from a base class to a derived class, like from QWidget to QTabWidget, it is inherently unsafe! If you have to do that, then, most of the time, you probably need to rethink the design of your code. But if you really cannot get around this, use dynamic_cast at least. And don't forget to check the result of the dynamic cast for NULL ;-)

    http://en.wikipedia.org/wiki/Dynamic_cast


  • Lifetime Qt Champion

    For QObjects derived classes, you should use qobject_cast, if it fails for another reason than wrong "class name" then it will indicate that you are doing something funky somewhere.


Log in to reply