Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Program.exe has stopped working

Program.exe has stopped working

Scheduled Pinned Locked Moved Solved General and Desktop
17 Posts 3 Posters 5.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • cpperC Offline
    cpperC Offline
    cpper
    wrote on last edited by cpper
    #1

    I'm trying to display a chart when clicking on a push button. My problem is the following: If I press two times on the button, the a chart is displayed two times; if I close the first chart , and then the second the program stops working. Closing the second widget and than the first works fine. Here is the code of the push button slot. The .pro file and everything else is fine:

    void MainWindow::on_pushButton_clicked()
    {
        QChart* chart = new QChart;
        QLineSeries* series = new QLineSeries;
    
        series->append(10,15);
        series->append(13,17);
        series->append(21,12);
        series->append(24,18);
    
        chart->addSeries(series);
        chart->createDefaultAxes();
    
        QChartView* chartView=new QChartView(chart);
        chartView->move(300,200);
        chartView->resize(1000,400);
    
        QEventLoop loop;
        chartView->setAttribute( Qt::WA_DeleteOnClose );
        connect(chartView,&QChartView::destroyed,&loop,&QEventLoop::quit);
        chartView->show();
    
        loop.exec();
        delete series;
    
    }
    
    

    I've created the loop and called chartView->setAttribute( Qt::WA_DeleteOnClose ); because I need to pause the function until I close the widget, or else the series are deleted. This is a as much as possible simplified version of the a bigger program.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      It looks like you are implementing that like a QDialog so why not use one to show your chart ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      cpperC 1 Reply Last reply
      1
      • SGaistS SGaist

        Hi,

        It looks like you are implementing that like a QDialog so why not use one to show your chart ?

        cpperC Offline
        cpperC Offline
        cpper
        wrote on last edited by
        #3

        @SGaist

        Commodity I guess, with directly displaying the widget I wouldn't need to declare another class. I've managed to find a solution to the problem by inheriting from QChartView and emitting a signal from overridden closeEvent function. But would it be a better idea to wrap the widget in a QDialog instead ?

        However, I'm still curios what is wrong in the original code, if you mind to explain.

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Likely the delete of the series object. The chart takes ownership of the series so technically you have a double deletion.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          cpperC 1 Reply Last reply
          1
          • SGaistS SGaist

            Likely the delete of the series object. The chart takes ownership of the series so technically you have a double deletion.

            cpperC Offline
            cpperC Offline
            cpper
            wrote on last edited by cpper
            #5

            @SGaist Don't think that is the problem, if I'm closing the second opened widget first, everything is ok.
            It also seems that the series are not deleted when the QChartView is destroyed. The QChart however, is destroyed. I've tested by doing qDebug()<<series after loop.exec().

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              How did you determine that the series wasn't destroyed ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              1
              • cpperC Offline
                cpperC Offline
                cpper
                wrote on last edited by
                #7

                By doing qDebug()<<series; after loop.exec(); which successfully prints QtCharts::QLineSeries(0x37e7530).
                Placing delete series; before qDebug()<<series; , or doing qDebug()<<chart; results in "program.exe has stopped working"

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Having a pointer with an address in doesn't make it valid. Calling delete on a pointer in C++ doesn't result in having it re-initialized. You have a dangling pointer that you are trying to delete.

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  cpperC 1 Reply Last reply
                  2
                  • cpperC Offline
                    cpperC Offline
                    cpper
                    wrote on last edited by cpper
                    #9

                    Try to open 2 or more charts and close them lifo. The instruction "delete series;" doesn't cause any trouble if doing so. If it's about dangling pointers why does this work ?

                    Also, the instruction qDebug()<<chart; alone blocks the program.

                    1 Reply Last reply
                    0
                    • SGaistS SGaist

                      Having a pointer with an address in doesn't make it valid. Calling delete on a pointer in C++ doesn't result in having it re-initialized. You have a dangling pointer that you are trying to delete.

                      cpperC Offline
                      cpperC Offline
                      cpper
                      wrote on last edited by
                      #10

                      @SGaist I also tried printing a point from the series by doing qDebug()<<series->at(0).x(); and get a valid result.

                      kshegunovK 1 Reply Last reply
                      0
                      • cpperC cpper

                        @SGaist I also tried printing a point from the series by doing qDebug()<<series->at(0).x(); and get a valid result.

                        kshegunovK Offline
                        kshegunovK Offline
                        kshegunov
                        Moderators
                        wrote on last edited by kshegunov
                        #11

                        @cpper
                        Consider this:

                        char * test = new char[4];
                        test[0] = 'A';
                        test[3] = 'C';
                        delete test; //< Now we don't have the memory anymore
                        
                        qDebug() << test[3]; //< Reading an invalid location, yet you'd probably get 'C' and no crash
                        

                        It's the same with objects, until memory is overwritten you have a good chance that your object is still there, so getting a value for:

                        qDebug() << series->at(0).x();
                        

                        just means nothing.

                        What does this print out:

                        void MainWindow::on_pushButton_clicked()
                        {
                            // ... Your code before loop.exec() goes here ...
                        
                            QPointer<QLineSeries> guarded(series);
                            loop.exec();
                        
                            if (!guarded)
                                qDebug() << "Ouch! We have a nasty ownership problem, we want to delete an object we don't own ...";
                            else  {
                                qDebug() << "We are okay, series points to a valid object";
                                delete series;
                            }
                        }

                        Read and abide by the Qt Code of Conduct

                        1 Reply Last reply
                        1
                        • cpperC Offline
                          cpperC Offline
                          cpper
                          wrote on last edited by cpper
                          #12

                          It prints ""We are okay, series points to a valid object".
                          If guarded pointer points to the QChart it prints ""Ouch! We have a nasty ownership problem, we want to delete an object we don't own ...";
                          So this finally confirms that the chart gets deleted but the series not, right ?

                          @SGaist said in Program.exe has stopped working:

                          Having a pointer with an address in doesn't make it valid. Calling delete on a pointer in C++ doesn't result in having it re-initialized. You have a dangling pointer that you are trying to delete.

                          After loop.exec() try qDebug()<<series , and qDebug()<<chart . The first one works but the second crashed the program.

                          Or consider this: QWidget* w=new QWidget(); qDebug()<<w; . This works and prints an address. But QWidget* w=new QWidget(); delete w; qDebug()<<w; crashes the program.
                          I'm not saying that you are wrong, but trying to qDebug() a deleted pointer crashes the program. Since qDebug()<<series worked for me means series wasn't deleted. Or ?

                          kshegunovK 1 Reply Last reply
                          0
                          • cpperC cpper

                            It prints ""We are okay, series points to a valid object".
                            If guarded pointer points to the QChart it prints ""Ouch! We have a nasty ownership problem, we want to delete an object we don't own ...";
                            So this finally confirms that the chart gets deleted but the series not, right ?

                            @SGaist said in Program.exe has stopped working:

                            Having a pointer with an address in doesn't make it valid. Calling delete on a pointer in C++ doesn't result in having it re-initialized. You have a dangling pointer that you are trying to delete.

                            After loop.exec() try qDebug()<<series , and qDebug()<<chart . The first one works but the second crashed the program.

                            Or consider this: QWidget* w=new QWidget(); qDebug()<<w; . This works and prints an address. But QWidget* w=new QWidget(); delete w; qDebug()<<w; crashes the program.
                            I'm not saying that you are wrong, but trying to qDebug() a deleted pointer crashes the program. Since qDebug()<<series worked for me means series wasn't deleted. Or ?

                            kshegunovK Offline
                            kshegunovK Offline
                            kshegunov
                            Moderators
                            wrote on last edited by
                            #13

                            @cpper said in Program.exe has stopped working:

                            So this finally confirms that the chart gets deleted but the series not, right ?

                            No, not necessarily. It means that series is not deleted directly (with delete), it can however be scheduled for deletion (with QObject::deleteLater). And one of the specific things about local event loops is that they don't process those events, they delegate them to the higher-level event loop. So, you may still be getting a double deletion. The other thing that you could try and it will ultimately show whether or not the object is deleted by the chart is if you attach to the QObject::destroyed signal (instead of deleting it explicitly):

                            void MainWindow::on_pushButton_clicked()
                            {
                                // ...
                                loop.exec();
                                // delete series;
                                QObject::connect(series, &QObject::destroyed, [] (QObject *) -> void {
                                    qDebug() << "Series is deleted in the parent event loop!"
                                });
                            }
                            

                            Of course, you can also just try substituting delete series with series->deleteLater(), which would solve your problem, if it is in fact a double deletion.

                            Read and abide by the Qt Code of Conduct

                            cpperC 1 Reply Last reply
                            1
                            • kshegunovK kshegunov

                              @cpper said in Program.exe has stopped working:

                              So this finally confirms that the chart gets deleted but the series not, right ?

                              No, not necessarily. It means that series is not deleted directly (with delete), it can however be scheduled for deletion (with QObject::deleteLater). And one of the specific things about local event loops is that they don't process those events, they delegate them to the higher-level event loop. So, you may still be getting a double deletion. The other thing that you could try and it will ultimately show whether or not the object is deleted by the chart is if you attach to the QObject::destroyed signal (instead of deleting it explicitly):

                              void MainWindow::on_pushButton_clicked()
                              {
                                  // ...
                                  loop.exec();
                                  // delete series;
                                  QObject::connect(series, &QObject::destroyed, [] (QObject *) -> void {
                                      qDebug() << "Series is deleted in the parent event loop!"
                                  });
                              }
                              

                              Of course, you can also just try substituting delete series with series->deleteLater(), which would solve your problem, if it is in fact a double deletion.

                              cpperC Offline
                              cpperC Offline
                              cpper
                              wrote on last edited by
                              #14

                              @kshegunov @SGaist

                              The slot is indeed called. So the conclusion of the illusion is that the chart is immediately destroyed after the widget is closed, but the series is later destroyed. This explains everything. Thanks guys for being pacient and making everything clear to me.

                              kshegunovK 1 Reply Last reply
                              0
                              • cpperC cpper

                                @kshegunov @SGaist

                                The slot is indeed called. So the conclusion of the illusion is that the chart is immediately destroyed after the widget is closed, but the series is later destroyed. This explains everything. Thanks guys for being pacient and making everything clear to me.

                                kshegunovK Offline
                                kshegunovK Offline
                                kshegunov
                                Moderators
                                wrote on last edited by
                                #15

                                @cpper
                                Yes, the object's deferred deletion is yet again deferred ...
                                Local event loops are discouraged in principle, and you can see why.

                                Read and abide by the Qt Code of Conduct

                                1 Reply Last reply
                                1
                                • cpperC Offline
                                  cpperC Offline
                                  cpper
                                  wrote on last edited by cpper
                                  #16

                                  This was the original code:

                                      QEventLoop loop;
                                      chartView->setAttribute( Qt::WA_DeleteOnClose );
                                      connect(chartView,&QChartView::destroyed,&loop,&QEventLoop::quit);
                                      chartView->show();
                                  
                                      loop.exec();
                                      delete series;
                                  

                                  Now that I've learned that deleting the chartView also deletes the chart,series, and axis, I've replaced the code with :

                                  chartView->setAttribute( Qt::WA_DeleteOnClose );
                                  chartView->show();
                                  

                                  And it works like a charm now. Of course, the complete version of the program.

                                  One last thing I've noticed: If I explicitly delete series, the program does not crash if it automatically wants to delete series (later). But if the program has already automatically deleted series and I try to explicitly delete it afterwards, I get the "program.exe has stopped working". That being said, it seems the automatic deletion(the ownership thing) checks firstly if the pointer is still valid, like you did in the example with the "guarded" pointer.

                                  kshegunovK 1 Reply Last reply
                                  0
                                  • cpperC cpper

                                    This was the original code:

                                        QEventLoop loop;
                                        chartView->setAttribute( Qt::WA_DeleteOnClose );
                                        connect(chartView,&QChartView::destroyed,&loop,&QEventLoop::quit);
                                        chartView->show();
                                    
                                        loop.exec();
                                        delete series;
                                    

                                    Now that I've learned that deleting the chartView also deletes the chart,series, and axis, I've replaced the code with :

                                    chartView->setAttribute( Qt::WA_DeleteOnClose );
                                    chartView->show();
                                    

                                    And it works like a charm now. Of course, the complete version of the program.

                                    One last thing I've noticed: If I explicitly delete series, the program does not crash if it automatically wants to delete series (later). But if the program has already automatically deleted series and I try to explicitly delete it afterwards, I get the "program.exe has stopped working". That being said, it seems the automatic deletion(the ownership thing) checks firstly if the pointer is still valid, like you did in the example with the "guarded" pointer.

                                    kshegunovK Offline
                                    kshegunovK Offline
                                    kshegunov
                                    Moderators
                                    wrote on last edited by kshegunov
                                    #17

                                    @cpper said in Program.exe has stopped working:

                                    That being said, it seems the automatic deletion(the ownership thing) checks firstly if the pointer is still valid, like you did in the example with the "guarded" pointer.

                                    It does, sort of - it removes the pending events for the object, because Qt has to guarantee that multiple calls to QObject::deleteLater don't lead to side effects (as is documented) .

                                    Read and abide by the Qt Code of Conduct

                                    1 Reply Last reply
                                    1

                                    • Login

                                    • Login or register to search.
                                    • First post
                                      Last post
                                    0
                                    • Categories
                                    • Recent
                                    • Tags
                                    • Popular
                                    • Users
                                    • Groups
                                    • Search
                                    • Get Qt Extensions
                                    • Unsolved