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

Can't find the invalid pointer



  • I'm working with qt5.15 in qtCreator in ubuntu 20.04 and g++. My program compiles and works fine until I close the main window becuase I get the error in the title of the question. I read that this error occurs when there is a invalid pointer, I tried to find it in my program but I couldnt.

    main.cpp

    #include "MainWindow.h"
    
    #include <QApplication>
    
        int main(int argc, char *argv[])
        {
            QApplication a(argc, argv);
            MainWindow w;
            w.show();
            return a.exec();
        }
    

    MainWindow.h

    #pragma once
    
    #include "Facelet.h"
    #include "Face.h"
    
    #include <QMainWindow>
    #include <QWidget>
    #include <QSpacerItem>
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
        using type = Face;
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    protected:
    
        virtual void resizeEvent(QResizeEvent*) override;
    
    private:
    
        void __init_spacers();
    
        QWidget* wid;
        type* object;
        QGridLayout* layout;
        QSpacerItem* spacer;
    
    };
    

    MainWindow.cpp

    #include "MainWindow.h"
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
    {
        object = new type();
        layout = new QGridLayout();
        wid = new QWidget();
        __init_spacers();
        layout->setContentsMargins(0,0,0,0);
        layout->addWidget(object, 1, 1);
        wid->setLayout(layout);
        setCentralWidget(wid);
    }
    
    MainWindow::~MainWindow()
    {
        delete spacer;
        delete object;
        delete layout;
        delete wid;
    }
    
    //protected
    
    void MainWindow::resizeEvent(QResizeEvent*) {
        int side = (size().width() < size().height()) ? size().width() : size().height();
        object->resize(side, side);
    }
    
    //private
    
    void MainWindow::__init_spacers() {
        spacer = new QSpacerItem(0,0, QSizePolicy::Expanding, QSizePolicy::Expanding);
        layout->addItem(spacer, 0, 1);//top
        layout->addItem(spacer, 1, 0);//left
        layout->addItem(spacer, 2, 1);//bootom
        layout->addItem(spacer, 1, 2);//right
    }
    

    Face.h

    #pragma once
    
    #include "Facelet.h"
    #include <QGridLayout>
    
    class Face : public QWidget {
    
        Q_OBJECT
    
    public:
    
        explicit Face(QWidget* parent = nullptr);
        ~Face();
    
        std::string get_pattern();
    
    protected:
    
        virtual void resizeEvent(QResizeEvent *event = nullptr) override;
    
    private:
    
        void __init_widget();
        void __init_layout();
        void __init_facelets();
        void __update_facelets(int side);
        void __delete_facelets();
    
        Facelet** facelets;
        QGridLayout* layout;
    
        constexpr static unsigned int SIDE = 248;
        constexpr static unsigned int SPACE = 10;
    
    };
    

    Face.cpp

    #include "Face.h"
    
    Face::Face(QWidget* parent) : QWidget(parent) {
        __init_facelets();
        __update_facelets(75);
        __init_layout();
        __init_widget();
    }
    
    Face::~Face() {
        __delete_facelets();
        delete layout;
    }
    
    std::string Face::get_pattern() {
        std::string result;
        for(int i = 0; i < 3; ++i) {
            for(int j = 0; j < 3; ++j) {
                result.push_back( char(Colors::list[facelets[i][j].id()].second) );
            }
        }
        return result;
    }
    
    //protected
    
    void Face::resizeEvent(QResizeEvent *event) {
        int side = (size().width() > size().height()) ? size().width() : size().height();
        int facelet_side = (side-8)/3;
        __update_facelets(facelet_side);
    }
    
    //private
    
    void Face::__init_widget() {
        this->resize(SIDE, SIDE);
        this->setMinimumSize(SIDE, SIDE);
        this->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
        this->setAttribute(Qt::WA_StyledBackground);
        this->setStyleSheet("background-color: black;");
        this->setLayout(layout);
    }
    
    void Face::__init_layout() {
        layout = new QGridLayout();
        layout->setSpacing(2);
        layout->setContentsMargins(2, 2, 2, 2);
        for(int i = 0; i < 3; ++i) {
            for(int j = 0; j < 3; ++j) {
                layout->addWidget(&facelets[i][j], i, j);
            }
        }
    }
    
    void Face::__init_facelets() {
        facelets = new Facelet*[3];
        for(int i = 0; i < 3; ++i) {
            facelets[i] = new Facelet[3];
        }
    }
    
    void Face::__update_facelets(int side) {
        for(int i = 0; i < 3;++ i) {
            for(int j = 0; j < 3; ++j) {
                facelets[i][j].setFixedSize(side, side);
            }
        }
    }
    
    void Face::__delete_facelets() {
        for(int i = 0; i < 3; ++i) {
            delete[] facelets[i];
        }
        delete[] facelets;
    }
    

    Facelette.h

    #pragma once
    
    #include "Colors.h"
    
    #include <QPushButton>
    #include <QPainter>
    
    class Facelet : public QPushButton {
    
        Q_OBJECT
    
    public:
    
        using id_type = Colors::Id;
    
        explicit Facelet(QWidget* parent = nullptr);
        explicit Facelet(Colors::Id color, QWidget* parent = nullptr);
        virtual ~Facelet();
    
        void reset();
        void set_color(Colors::Id);
        id_type id();
    
    protected:
        virtual void paintEvent(QPaintEvent *e = nullptr) override;
    
    public slots:
    
        void __change_color();
    
    private:
        
        int _Id;
    
    };
    

    Facelet.cpp

    #include "Facelet.h"
    #include <QStyleOption>
    
    Facelet::Facelet(QWidget* parent) : QPushButton(parent) {
        reset();
        connect(this, SIGNAL(clicked()), SLOT(__change_color()));
    }
    
    Facelet::Facelet(Colors::Id id_, QWidget* parent) : QPushButton(parent) {
        set_color(id_);
        connect(this, SIGNAL(clicked()), SLOT(__change_color()));
    }
    
    Facelet::~Facelet() {}
    
    void Facelet::reset() {
        _Id = -1;
        this->setStyleSheet("background-color:lightGray;");
    }
    
    void Facelet::set_color(Colors::Id _id) {
        _Id = _id;
        setStyleSheet(QString("background-color:")+Colors::list[_Id].first+";");
    }
    
    Facelet::id_type Facelet::id() {
        return Facelet::id_type(_Id);
    }
    
    //protected
    
    void Facelet::paintEvent(QPaintEvent *) {
        QStyleOption opt;
        opt.init(this);
        QPainter p(this);
        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
    }
    
    //private slots
    
    void Facelet::__change_color() {
        _Id = (_Id >= 5) ? 0 : (_Id+1);
        set_color(Colors::Id(_Id));
    }
    

    Colors.h

    #pragma once
    
    #include "Rubix/Rubix.h"
    
    #include <array>
    #include <utility>
    #include <QColor>
    
    
    struct Colors {
    
        using value_type = typename std::pair<QString, rbx::RColor>;
        using array_type = typename std::array<value_type, 6>;
        enum Id { Yellow, Red, Green, Orange, Blue, White };
        static array_type list;
    
    };
    

    Colors.cpp

    #include "Colors.h"
    
    Colors::array_type Colors::list = {
        Colors::value_type("yellow", rbx::YELLOW),
        Colors::value_type("rgb(255, 20, 20)", rbx::RED),
        Colors::value_type("rgb(35, 255, 35)", rbx::GREEN),
        Colors::value_type("rgb(255, 130, 20)", rbx::ORANGE),
        Colors::value_type("blue", rbx::BLUE),
        Colors::value_type("white", rbx::WHITE),
    };
    

    when I close the window I get the following error

    21:07:22: Starting /home/kubuntu/Desktop/projects/x64/RubbixSolver/Debug/GUI/build-GUI-Desktop_Qt_5_15_2_GCC_64bit-Profile/GUI ...
    21:07:46: The program has unexpectedly finished.
    21:07:46: The process was ended forcefully.
    21:07:46: /home/kubuntu/Desktop/projects/x64/RubbixSolver/Debug/GUI/build-GUI-Desktop_Qt_5_15_2_GCC_64bit-Profile/GUI crashed.
    

    If I start the debug when I close the main window it says there is a problem in Face::~Face(), a small message-window pops up with the following message'The inferior stopped because it received a signal from the operating system. Signal name : SIGSEGV Signal meaning : Segmentation fault, the conosle debug displays a bounch of ```
    RTTI symbol not found for class 'QObject'



  • @Gallo-Magico said in Can't find the invalid pointer:

    void Face::__delete_facelets() {
    for(int i = 0; i < 3; ++i) {
    delete[] facelets[i];
    }
    delete[] facelets;
    }

    @Gallo-Magico I feel in destructor you are doing double deletion.
    deleting the memory which was already deleted.

    delete[] facelets; //comment it out
    


  • @nagesh getting the same error in the same destructor, I also tried to uncomment delete layout but I always get the same error



  • void Face::__init_layout() {
    ....
    layout->addWidget(&facelets[i][j], i, j);
    }
    

    You have added the facelets objects to the layout.
    The ownership of item is transferred to the layout, and it's the layout's responsibility to delete it.
    I feel no need to free the memory in the destructor for the facelets and as well as layout.

    Refer object tree & ownership details
    https://doc.qt.io/qt-5/objecttrees.html



  • @nagesh I still get error but is a different message

    The inferior stopped because it received a signal from the operating system.
    
    Signal name : 
    SIGABRT
    Signal meaning : 
    Aborted
    

    I get this error in Facelet::~Facelet() and the console application displays munmap_chunk(): invalid pointer.
    I also tried to turn facelets into a Facelet*** and treat Facelet[i][j] as a pointer instead as an object, but I get the same error I got at the begin



  • @Gallo-Magico do you still get these errors when you are not deleting/freeing?

    //__delete_facelets();
        //delete layout;
    


  • @nagesh yes



  • @Gallo-Magico said in Can't find the invalid pointer:

    MainWindow::~MainWindow()
    {
    delete spacer;
    delete object;
    delete layout;
    delete wid;
    }

    Same problem here. If QObjects have a parent they get deleted when the parent gets deleted automatically, if you do it manually it's a double deletion.
    If debugging is becoming a mess change the type of your QObjects pointer to QPointer so the pointers will be set to null automatically on deletion and you won't be able to double-delete them


  • Qt Champions 2017

    @VRonin said in Can't find the invalid pointer:

    Same problem here. If QObjects have a parent they get deleted when the parent gets deleted automatically, if you do it manually it's a double deletion.

    No it is not. The child notifies the parent when it goes away, so the parent detaches it from the list.


  • Lifetime Qt Champion

    @kshegunov said in Can't find the invalid pointer:

    No it is not. The child notifies the parent when it goes away, so the parent detaches it from the list.

    @VRonin forgot a sentence in if you do it manually it's a double deletion. - if you do it manually after the parent deleted it's children it's a double deletion :)



  • @VRonin I already deleted those too, but now I'm getting an error in Facelet::~Facelet(), the error is

    The inferior stopped because it received a signal from the operating system.
    
    Signal name : 
    SIGABRT
    Signal meaning : 
    Aborted
    


  • I figured out,there were a bounch of problem, first of all I used to double delete child widgets, like the layout(child of the main widget) and the other widget into the layout(child of the layout), then I got all my destructors empty but I got an error caused by deleting a location memory not allocated with new. In my case the dynamic matrix of facelet don't allocate the memory for each Facelet, then I turned facelets from Facelet** facelets into a Facelet*** facelets and changed init_facelets() to

    void Face::init_facelets() {
        facelets = new Facelet**[3];
        for(int i = 0; i < 3; ++i) {
            facelets[i] = new Facelet*[3];
            for(int j = 0; j < 3; ++j) {
                facelets[i][j] = new Facelet();
            }
        }
    }
    

    When the program ends, Face::~Face() frees all the location corresponding to facelets[i][j], then I had to free the rest of the matrix, so now Face::~Face() looks like

    Face::~Face() {
        for(int i = 0; i < 3; ++i) {
            delete[] facelets[i];
        }
        delete[] facelets;
    }
    

    Now it works with no problem or any issue



  • @Gallo-Magico said in Can't find the invalid pointer:

    layout->addWidget(&facelets[i][j]

    This sets Face as parent of facelets[i][j] so same error as before you are double deleting a QObject as the parent already deleted it

    No it is not. The child notifies the parent when it goes away, so the parent detaches it from the list.

    Good observation, I didn't explain myself well there.

    P.S.
    from https://en.cppreference.com/w/cpp/keyword

    • identifiers with a double underscore anywhere are reserved
    • identifiers that begin with an underscore followed by an uppercase letter are reserved

    You should rename your methods/members



  • @VRonin I know about the methods that begin with __, I already changed