You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qt中以已删除对象为收发参数调用disconnect是否安全?

问题解答

核心结论

你的代码存在未定义行为,不是简单的调用失败返回false。

原因说明

  • Qt的disconnect函数只会安全处理nullptr参数,并不会校验传入的指针是否指向已经释放的内存:
    • 当子窗口被关闭销毁时,mPreviouslyActiveWidget成为野指针,指向已经被系统回收的内存
    • 此时disconnect内部会尝试访问该指针对应QObject的内部连接表等私有数据,访问野内存属于标准C++未定义行为,可能出现程序崩溃、随机异常等问题
  • 额外说明:QObject对象销毁时会自动断开所有关联的信号槽连接,你原本的手动断开逻辑如果指针有效的话属于冗余操作,问题的核心是野指针的访问风险。

修复方案

最简单可靠的方案是将mPreviouslyActiveWidget的类型从原生指针MyWidget*替换为Qt提供的智能指针QPointer<MyWidget>:

  • QPointer是专门用于持有QObject对象的弱智能指针,当指向的QObject对象被销毁时,QPointer会自动被置为nullptr
  • 此时向disconnect传入nullptr参数,函数会直接安全返回false,不会触发任何内存访问

修复后的参考代码:

// 头文件成员变量声明替换为
QPointer<MyWidget> mPreviouslyActiveWidget;

// 槽函数实现修改为
void MainWindow::SubWindowActivated(QMdiSubWindow* subWindow)
{
    MyWidget* activeWidget = subWindow ? qobject_cast<MyWidget*>(subWindow->widget()) : nullptr;
    if (activeWidget == mPreviouslyActiveWidget)
    {
        return;
    }

    // 此时mPreviouslyActiveWidget如果已经销毁则为nullptr,disconnect安全无风险
    disconnect(this, nullptr, mPreviouslyActiveWidget, nullptr); 
    disconnect(mPreviouslyActiveWidget, nullptr, this, nullptr);

    // 新增与当前activeWidget的连接逻辑
    if (activeWidget) {
        // 你的连接实现
    }

    mPreviouslyActiveWidget = activeWidget;
}

如果不想用QPointer,也可以在持有原生指针的同时,绑定mPreviouslyActiveWidget的destroyed信号,收到信号时将指针置空,但实现成本远高于直接使用QPointer。

内容的提问来源于stack exchange,提问作者Unimportant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 08:06:04