There is the main window MainWindow, there is its child window, which is created in the slot of the main window MainWindow - MapsManager (this). The problem is that if the child window is open and I click on the cross of the main window (well, I’m trying to close the main window, which means the entire application window), then I’ll go to the MainWindow destructor, then MapsManager destructor, then lambda, there kicks out a segfolt on any line with access to ui. Why does the MainWindow destructor work before the child?

void MainWindow::slotMapsManager() { // ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ Π½Π΅ Π·Π°ΠΏΡƒΡ‰Π΅Π½ Π»ΠΈ Π²ΠΈΠ΄ΠΆΠ΅Ρ‚ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π° ΠΊΠ°Ρ€Ρ‚ if(mapsManagerPtr_) return; if(foundPointPtr_) foundPointPtr_->close(); WaterBody::getInstance().hidePoint(); // Π£ΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ Ρ€Π°Π·ΠΌΠ΅Ρ€ Π²ΠΈΠ΄ΠΆΠ΅Ρ‚Π° для ΠΏΠΎΠ²Ρ‹ΡˆΠ΅Π½ΠΈΡ Ρ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒ ΠΈ удобства ΠΊΠ°Π»ΠΈΠ±Ρ€ΠΎΠ²ΠΊΠΈ, setWindowState(Qt::WindowMaximized); // Π—Π°Ρ„ΠΈΠΊΡΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π°Π·ΠΌΠ΅Ρ€ Π²ΠΈΠ΄ΠΆΠ΅Ρ‚Π° setFixedSize(width(), height()); // НСобходимо ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Π½Π΅Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹ΠΌΠΈ ΠΊΠ½ΠΎΠΏΠΊΠΈ поиска ΠΈ создания Ρ‚ΠΎΡ‡Π΅ΠΊ ui->pushButtonCreateGamePoint->setEnabled(false); ui->pushButtonFindGamePoint->setEnabled(false); ui->menuBar->setEnabled(false); ui->lineEditPointX->setValidator(new QIntValidator(0, 9999, this)); ui->lineEditPointY->setValidator(new QIntValidator(0, 9999, this)); ui->lineEditPointX->setReadOnly(true); ui->lineEditPointY->setReadOnly(true); ui->lineEditPointX->clear(); ui->lineEditPointY->clear(); mapsManagerPtr_ = new MapsManager(this); // БоСдиняСт сигнал закрытия Π²ΠΈΠ΄ΠΆΠ΅Ρ‚Π° с лямбдой connect(mapsManagerPtr_, &MapsManager::destroyed, this, [this]() { // Π’Π΅Ρ€Π½ΡƒΡ‚ΡŒ стандартныС ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹Π΅ ΠΈ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹Π΅ Ρ€Π°Π·ΠΌΠ΅Ρ€Ρ‹ Π²ΠΈΠ΄ΠΆΠ΅Ρ‚Π° для ΠΎΡ‚ΠΌΠ΅Π½Ρ‹ фиксации setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); setMinimumSize(MINIMUM_WIDTH, MINIMUM_HEIGHT); //WaterBody::getInstance().showPoint(); // Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΡΡ‚ΡŒ ΠΊΠ½ΠΎΠΏΠΊΠ°ΠΌ поиска ΠΈ создания Ρ‚ΠΎΡ‡Π΅ΠΊ ui->pushButtonCreateGamePoint->setEnabled(true); ui->pushButtonFindGamePoint->setEnabled(true); ui->menuBar->setEnabled(true); // Π’Π°Π»ΠΈΠ΄Π°Ρ‚ΠΎΡ€ для ΠΏΠΎΠ»Π΅ΠΉ отобраТСния ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚. ΠΠ΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ минус, Π·Π°Ρ‚Π΅ΠΌ 0-999 ui->lineEditPointX->setValidator(new QRegExpValidator(QRegExp("(-\\d{2})|(\\d{3})"), this)); ui->lineEditPointY->setValidator(new QRegExpValidator(QRegExp("(-\\d{2})|(\\d{3})"), this)); ui->lineEditPointX->setReadOnly(false); ui->lineEditPointY->setReadOnly(false); ui->lineEditPointX->clear(); ui->lineEditPointY->clear(); }); mapsManagerPtr_->show(); } 
  • it seems like there is nothing criminal ... and if in the lambda you remove all references that cause a segfolt, then he goes into the destructor of the main window? - bronstein87 8:04 pm
  • Ops! I still get to the destructor of the main window earlier than to the child’s destructor, that with the commented lambda that without. Is this normal behavior? Now I will rewrite the description of the problem. Yesterday I didn’t seem to fall into the destr of the main thing, although I’ve ruled some things since Now it is clear why ui is no longer at this moment, but it is not clear why at first it does not try to remove all the children, and only then the main thing. - FliXis pm
  • It seems to solve the problem by adding ui = nullptr; in the MainWindow destructor right after delete ui; And setting the test in the lambda if (! Ui) return; It looks like a crutch of course. Maybe there is a more normal approach? Or is this need due to the lambda with the signal destroyed and it was necessary to do so initially? And the sequence of destructors is completely normal, is it? - FliXis
  • Well, see, ui belongs to QMainWindow, and deleteChildren is called at the very end of the QObject destructor. Since the order of calling destructors from the child to the parent, by the time the signal was destoroyed, there was nothing left of your ui, because it was removed in the QMainWindow destructor. - bronstein87 pm
  • It sounds contradictory of course, it turns out that the parent destructor is initially still called, after removing almost everything and everything in it, the child is called, and after it the parent again, where the terminal operations continue. It turns out that the order of terminal calls is not from the child to the parent, but some kind of circulation. Thank you for helping to solve the problem! - FliXis

1 answer 1

Your QMainWindow deletes the child objects only in the constructor of its most basic class QObject , which, as you know, is called at the very end. By that time, there are no data members, in particular, ui , of the QMainWindow class, since its destructor was called earlier. As for a more beautiful solution to your problem, it may be worth redefining your MapManager and throwing any special signals in it that will attach to your lambda.