Pregunta

I have problem in ensuring the dialog is closed/released with the following Qt codes.

 //Segment 1: To open a 'wait' dialog for some long-running tasks
 void MainWindow::ui_showProgressDialog(QString title) {
     dlgProgress = new QProgressDialog(title, tr("Cancel"), 0, 0, this);
     dlgProgress->setAttribute(Qt::WA_DeleteOnClose); // line 1
     dlgProgress->setModal(true);
     dlgProgress->show();
     connect(voidWatcher, SIGNAL(finished()),
             this, SLOT(onPopulationFile()));
 }

 //Segment 2: Attempts to close the 'wait' dialog
 void MainWindow::onPopulationFile() {
    qDebug((dlgProgress == NULL) ? "true" : "false");
    if (dlgProgress) // 
    {
        qDebug("0");
        dlgProgress->close(); // line 2
        qDebug("1");
    }
    qDebug((dlgProgress == NULL) ? "true" : "false");
 }

Issue: When I trigger the call 'ui_showProgressDialog' twice, the second call always crash my program. Originally, my code has no line 1 of segment 1, and from the QtCreator, it always crashes on line 2 of segment 2. Debug message shows as follow

// first call to onPopulationFile
false
0
1
false
// second call to onPopulationFile
false
0
*** CRASH ***    

I read the documentation that NEVER delete objects from different threads, I'm doubt that the call 'onPopulationFile' is invoked from a non-main thread. So I added the line 1 to segment to let the program decide when the delete the object. But it seems not work. Any suggestion to the problem?

Experiment done: If I replace QProgressDialog with QDialog, the program goes without crashes, and the debug message show

// first call to onPopulationFile
false
0
1
false
// second call to onPopulationFile
false
0
1
false

So,

  • Why the second null test in segment 2 always fail? [Edit: I have to explicitly set the variable to NULL]
  • Is there any better way to close the 'wait' dialog?
  • I try to close/release the dialog as I want release memory as soon as possible. Do I really need to manually delete the dialog?

Platform: Qt Opensource 4.8 (x64), Windows 7 (x64), MinGW (rubenvb 4.7.2)

¿Fue útil?

Solución

dlgProgress->setAttribute(Qt::WA_DeleteOnClose); deletes the widget when it is closed. As you are calling dlgProgress->close();, after this line the object it points to has been freed, and dlgProgress is now a invalid pointer.

You need to set dlgProgress to null after any call to close, or event better, use the signal Qobject::destroyed().

EDIT:

Qt::WA_DeleteOnClose specify that the object will be deleted if a close event happens. Not exactly how much time it will take. For instance if they are using QObject::deleteLater(), then the object is not deleted right away. Even if it is not the case , pieces of code like

 A* a = new A;
 a->dosomething();
 delete a;
 a->dosomething();

are undefined behavior. The second call to a->dosomething(); may crash (if you are lucky) or may not crash.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top