0

(Sorry for my future mistakes, I am fr)

I am creating a program to control the pc with a phone in c++ ( https://github.com/titicplusplus/PCPhone )

The server part works good, so I would like to add graphics interfaces for user, I decided to use QT.

When I stop the program QT, I have segmentation fault, and that stops the server.

My function that run the graphic interface:

void start_g(int argc, char **argv)
{
    QApplication app(argc,argv);
    QFile File(":/stylesheet.qss");                                                  
    File.open(QFile::ReadOnly);
    QString StyleSheet = QLatin1String(File.readAll());

    app.setStyleSheet(StyleSheet);
    

    ui interface; //QWidget window

    interface.start(); 

    std::cout << "start gui" << std::endl;

    interface.show();
    app.exec(); //return 0

    return;
}

I encapsulated the code in a function because I would like to run it in a thread, but for now during my tests, I don't do this.

Here is my class ui (user interface)

class ui : public QWidget
{
    public:
        ui();
        void start();
        void change_file();
        void change_port();

        void freset();
        void fapply();
        ~ui(); //Here is the problem

    private:
        openf f_open; //to open the extension s file

        std::unique_ptr<QFormLayout> formLayout;
        std::unique_ptr<QGroupBox> settings;
        std::unique_ptr<QVBoxLayout> main_layout;


        std::unique_ptr<QGridLayout> grid;
        std::vector< std::vector< std::unique_ptr<QPushButton> > > tab2d;
        std::unique_ptr<QGroupBox> all_button;
        std::unique_ptr<QSpinBox> port_l;
        std::unique_ptr<QPushButton> button_f;
        std::unique_ptr<QPushButton> apply;
        std::unique_ptr<QPushButton> reset;
        std::unique_ptr<QLabel> text_f;


};

and the important function

ui::ui() {}

void ui::start()
{
    grid = std::make_unique<QGridLayout>( this );
    
    /** Code that you don't need, I guess **/

    std::cout << "setting part" << std::endl;
    
    all_button = std::make_unique<QGroupBox>("Slide");
    all_button->setLayout(grid.get());

    port_l =std::make_unique<QSpinBox>(this);
    port_l->setMaximum(65535);
    port_l->setValue( config_json["port"].get<int>() );

    button_f = std::make_unique<QPushButton>("Open Image" ,this);
    text_f = std::make_unique<QLabel>(QString::fromStdString(fs::absolute(config_json["image"].get<std::string>())), this);

    apply = std::make_unique<QPushButton>("           Apply          " ,this);
    reset = std::make_unique<QPushButton>("Reset" ,this);

    //connect(button_f.get(), &QPushButton::clicked, this, &ui::change_file);
    connect(port_l.get(), QOverload<int>::of(&QSpinBox::valueChanged), this, &ui::change_port);
    connect(apply.get(), &QPushButton::clicked, this, &ui::fapply);
    connect(reset.get(), &QPushButton::clicked, this, &ui::freset);

    //auto fileName = QFileDialog::getOpenFileName(&window, "Open Image", "/home/$USER", ("Image Files (*.png *.jpg *.bmp)"));

    formLayout = std::make_unique<QFormLayout>();
    formLayout->addRow("The port", port_l.get());
    formLayout->addRow(text_f.get(), button_f.get()); //////////The problem is here
    //formLayout->addRow(apply.get(), reset.get());

    settings = std::make_unique<QGroupBox>("Settings");
    settings->setLayout(formLayout.get());


    main_layout = std::make_unique<QVBoxLayout>(this);

    main_layout->addWidget(all_button.get());
    main_layout->addWidget(settings.get());

}

So I saw on google, the problem come with the pointers and they destroy, so I try this

ui::~ui()
{
    main_layout = nullptr;
    settings = nullptr;
    all_button = nullptr;

    std::cout << "1u" << std::endl;
    button_f = nullptr;
    std::cout << "2u" << std::endl;
    text_f = nullptr;
    std::cout << "3u" << std::endl;
    apply = nullptr;
    std::cout << "4u" << std::endl;

    reset = nullptr;
    std::cout << "5u" << std::endl;
    grid = nullptr;
    

    std::cout << "bye bye" << std::endl;
}

The result is [ the errors are in french so I try to translate it ]:

    1u
    Segmentation fault (core dumped)

When I delete this line formLayout->addRow(text_f.get(), button_f.get());

There are no problems the deference of text_f and button_f, but with the next (apply and reset).

    1u
    2u
    3u
    Segmentation fault (core dumped)

On google, I saw a lot a time the people use the pointer and not the std::unique_ptr with qt, but I saw in general that people say "the smart pointer are better than the normal pointer. Also, I try to replace button_f.get() to std::move(button_f).get() but that doesn't work.

For information, I am on Ubuntu 20.04, with g++-9.3 and qt5. Thank you in advance for your answers !

pptaszni
  • 5,591
  • 5
  • 27
  • 43
  • Please copy paste crashed thread call stack, so we could know where it crashed. – Marek R Jun 11 '21 at 10:08
  • 1
    Why do you use `std::make_unique` at first place? You better to go with the raw pointers for objects of Qt classes. – vahancho Jun 11 '21 at 10:14
  • 2
    `Qt` (and `QObject` in particular) has its own ownership model for object hierarchies but your `std::unique_ptr` instances also assume ownership. Hence the problems you see. – G.M. Jun 11 '21 at 10:18

1 Answers1

0

Thanks G.M. and vahancho

I understand why I don't need to do std::unique_ptr .

When I learn C++ and pointer, there are rule : write one delete for every new, or better, use the smart pointer.

But with this two topics:

https://codereview.stackexchange.com/questions/43189/deleting-pointers-in-qt5/43201

Deleting Pointer to widget Qt C++

For the QT object, it's QT that deletes the pointers when the class is delete. So I just need to need change all of my std::unique_ptr in raw pointer.