Qt疑难问题-模态窗口父类被析构

最近遇到一个朋友,问了我一个刁钻的问题,当你模态弹出一个窗体时,后台把这个窗体的父类给析构了,这个时候会出现什么样的状况?函数

听到问题后我真是一脸懵逼呀!历来没有这么写过代码。oop

随后写了一个简单的测试demo,跟踪了下Qt的源码,得出以下结论:测试

  1. 首先程序不会崩溃
  2. 模态窗口会被析构并关闭

带着这两个问题咱们来研究下Qt的代码ui

一、测试代码

测试代码超级简单,就是当咱们的模态窗体弹出时,使用定时器10s后析构了其父类obj对象this

QPushButton * obj = new QPushButton;
QTimer::singleShot(10000, this, [&obj]() {
    delete obj;
    obj = nullptr;
});
QDialog * p = new QDialog(obj);
p->exec();

二、堆栈调用

首先咱们来看下模态窗口析构时,是由谁触发的,以下图所示,从堆栈能够很清楚的看到是父类按钮析构时,析构其全部子窗口干的。code

三、分析代码

a、QDialog::exec

int QDialog::exec()
{
    ...
    QEventLoop eventLoop;
    d->eventLoop = &eventLoop;
    (void) eventLoop.exec(QEventLoop::DialogExec);
    ...
}

当咱们调用QDialog的exec方法时,内部开启了一个QEventLoop事件循环对象

b、QEventLoop::exec

int QDialog::exec()
{
    ...
    while (!d->exit.loadAcquire())
        processEvents(flags | WaitForMoreEvents | EventLoopExec);
    ...
}

这个方法里边就是一直死循环处理咱们的事件,当d->exit.loadAcquire()返回不为false时,事件循环退出,也就是咱们的模态窗体要关闭了。接口

下面咱们来分析d->exit.loadAcquire()这个接口为何返回了真事件

首先我给全部调用d->exit.storeRelease方法的地方都打了断点,发现是在QEventLoop::exit函数中命中断点,看了下调用堆栈,没毛病,一切正常。源码

相关文章
相关标签/搜索