Why did I get a 'Debug Assertion Failed' in this QGridLayout project?



  • I was trying out QGridLayout, and I wanted to see if I could place a grid layout within another grid layout. I made three pushbuttons, and placed 2 of them in a smallGrid. I added the smallGrid to the bigGrid, along with the last pushbutton I initialized. The program ran, but on exit, I got a window with an error that included this:

    |||||
    Microsoft Vistual C++ Runtime Library
    Debug Assertion Failed!
    ...
    Expression: _CrtlsValidHeapPointer(block)
    |||||

    Why did I get this error? The program still ran. Did I forget to add something when I made my QGridLayout instances?

    #include <QtWidgets>
    #include <QPushButton>
    
    int main(int argc, char *argv[]) {
        QApplication app(argc, argv);
        QWidget window;
        window.resize(320, 340);
        window.show();
    
        QPushButton a,b,c;
        a.setText("A");
        b.setText("B");
        c.setText("C");
        a.show();
        b.show();
        c.show();
    
        QGridLayout smallGrid;
        smallGrid.addWidget(&a,0,0);
        smallGrid.addWidget(&b,1,0);
    
        QGridLayout bigGrid;
        bigGrid.addLayout(&smallGrid,0,0);
        bigGrid.addWidget(&c,0,1);
    
        window.setLayout(&bigGrid);
    
        return app.exec();
    
    }
    

  • Qt Champions 2016

    :::Pure Guessing:::

    Hi

    smallGrid.addWidget(&a,0,0); This owns the widget. The layout will delete the Widget.

    QPushButton a,b,c; // this will be deleted when running out of scope.

    So a,b,c might be deleted twice. From layout and then from scope.

    You can fix this by newing the buttons or by using a widget and not main for the code.



  • Oh, ok. I didn't know widgets were deleted after addWidget. I tried placing all my code in a subclass of QWidget in a "header.h", then I put TestWidget widget; window.setLayout(&(widget.bigGrid)); in my main.cpp. It didn't work, still got the debug error. Was that what you meant by "using a widget"? Here's my class definition for TestWidget that I used. Also, what did you mean by "newing the buttons"? QPushButton doesn't seem to have a "renew" function with it.

    class TestWidget: public QWidget {
        Q_OBJECT
    public:
        TestWidget(QWidget *parent = 0 ): QWidget(parent) {
            setup();
        }
    
        QPushButton a,b,c;
        QGridLayout smallGrid;
        QGridLayout bigGrid;
    
        void setup() {
            a.setText("Test");
            smallGrid.addWidget(&a,0,0);
            smallGrid.addWidget(&b,1,0);
            bigGrid.addLayout(&smallGrid,0,0);
            bigGrid.addWidget(&c,0,1);
        }
    };
    

  • Qt Champions 2016

    Hi
    Yes moving to widget seems much cleaner :) Good work.

    • Also, what did you mean by "newing the buttons"

    Sorry. badly told.
    What I mean is
    QPushButton *a = new QPushButton ();
    When you new it,
    it means that it would NOT be deleted by scope, only the layout / parent/owner.

    If you are not aware of Qt parent child ownership system, you best read up on it to avoid huge "ohhhh" experiences.
    http://doc.qt.io/qt-5/objecttrees.html

    Basically it means when you give it parent
    QPushButton *a = new QPushButton (this); // this is parent
    or add to layout
    That object now owns it and will delete it for you.



  • Oh ok, I'll look more into the link. It works now, both in main and in TestWidget class. Allocating on the stack has worked for me until this case, so I'll start allocating on the heap with "new". Thanks!


  • Qt Champions 2016

    @DragonautX
    There is nothing wrong with using the stack, ( at all)
    but one must understand the Owner system as not to crash.
    So often "new" the widgets to avoid deletion conflicts.
    But there are many cases where stack is pretty fine and issue-less.

    Like showing a dialog

    void Ask() {
    MyDialog Dia;
    Dia.exec(); // blocking
    ...
    }



  • Oh ok, so most of the time I can choose between either stack or heap. Looking at your link, in this case I guess the order of the widget initializations is important, but using "new" and the heap instead of the stack allows for constructors/destructors to be called in any order, allowing my project to run without errors.


  • Qt Champions 2016

    @DragonautX
    Yes, both stack and heap work
    but as you have seen , the auto delete system does require you to think
    slightly more about it when using the stack.


Log in to reply
 

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