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

Qt6/C++中SQL数据库连接关闭报错排查求助

Qt6/C++数据库连接关闭错误排查与解决

问题现象

运行代码时出现以下报错:

QSqlDatabasePrivate::removeDatabase: connection 'createRequestConnection' is still in use, all queries will cease to work.

代码中并未使用QSqlQuery执行查询,但始终无法定位问题根源。

相关代码

CreateRequestWindow.h

#ifndef CREATEREQUESTWINDOW_H
#define CREATEREQUESTWINDOW_H

#include <QWidget>
#include <QString>
#include <QSqlDatabase>

QT_BEGIN_NAMESPACE
namespace Ui {
class CreateRequestWindow;
}
QT_END_NAMESPACE

class CreateRequestWindow : public QWidget
{
    Q_OBJECT
public:
    explicit CreateRequestWindow(const QString& login, QWidget *parent = nullptr);
    ~CreateRequestWindow();

private slots:
    void on_pushButton_close_clicked();
    void on_pushButton_create_clicked();

signals:
    void windowClosed();

private:
    QString userLogin;
    Ui::CreateRequestWindow* ui;
    QSqlDatabase db;
    void openDatabaseConnection();
};

#endif // CREATEREQUESTWINDOW_H

CreateRequestWindow.cpp

#include "createrequestwindow.h"
#include "ui_createrequestwindow.h"
#include <QSqlQuery>
#include <QDateTime>

CreateRequestWindow::CreateRequestWindow(const QString& login, QWidget *parent)
    : QWidget(parent)
    , userLogin(login)
    , ui(new Ui::CreateRequestWindow)
{
    openDatabaseConnection();
    ui->setupUi(this);
}

CreateRequestWindow::~CreateRequestWindow(){
    db.close();
    QSqlDatabase::removeDatabase("createRequestConnection");
    delete ui;
}

void CreateRequestWindow::on_pushButton_close_clicked()
{
    this->close();
}

void CreateRequestWindow::on_pushButton_create_clicked()
{
    emit windowClosed();
}

void CreateRequestWindow::openDatabaseConnection(){
    if (!QSqlDatabase::contains("createRequestConnection")) {
        db = QSqlDatabase::addDatabase("QODBC", "createRequestConnection");
        db.setDatabaseName("zxctatar");
        if(!db.open()){
            qDebug() << "Failed open database CreateRequestWindow\n";
            return;
        }
    } else {
        db = QSqlDatabase::database("createRequestConnection");
    }
}

ClientWindow.h

#ifndef CLIENTWINDOW_H
#define CLIENTWINDOW_H

#include <QWidget>
#include <createrequestwindow.h>
#include <QSqlDatabase>

QT_BEGIN_NAMESPACE
namespace Ui {
class ClientWindow;
}
QT_END_NAMESPACE

class ClientWindow : public QWidget
{
    Q_OBJECT
public:
    explicit ClientWindow(const QString& userLogin, QWidget *parent = nullptr);
    ~ClientWindow();

private slots:
    void on_pushButton_close_clicked();
    void on_pushButton_createRequest_clicked();
    void updateWindow();
    void closeCreateRequestWindow(CreateRequestWindow* createRequestWindow);

private:
    QString userLogin;
    Ui::ClientWindow *ui;
    void showRequests(const QString& userLogin);
    void openDatabaseConnection();
    QSqlDatabase db;
};

#endif // CLIENTWINDOW_H

ClientWindow.cpp(与CreateRequestWindow交互部分)

void ClientWindow::on_pushButton_createRequest_clicked()
{
    CreateRequestWindow* createRequestWindow = new CreateRequestWindow(userLogin);
    createRequestWindow->setAttribute(Qt::WA_DeleteOnClose);
    createRequestWindow->show();
    connect(createRequestWindow, &CreateRequestWindow::windowClosed, this, [=](){
        closeCreateRequestWindow(createRequestWindow);
    });

    connect(createRequestWindow, &QObject::destroyed, this, [=](){
        disconnect(createRequestWindow, &CreateRequestWindow::windowClosed, this, nullptr);
    });
}

void ClientWindow::closeCreateRequestWindow(CreateRequestWindow* createRequestWindow){
    createRequestWindow->close();
}

问题原因

报错的核心是:调用QSqlDatabase::removeDatabase时,类成员db仍持有该连接的实例引用。Qt要求所有关联到该连接名称的QSqlDatabase对象都销毁后,才能安全执行removeDatabase。当前析构函数中,先执行关闭连接、移除连接操作,而db作为类成员会在析构函数执行完毕后才销毁,导致Qt检测到还有活跃的连接引用,抛出警告。

解决方案

调整析构函数执行顺序,先断开db与连接的关联,再调用removeDatabase:

修改CreateRequestWindow的析构函数

CreateRequestWindow::~CreateRequestWindow(){
    db.close();
    // 重置db,断开与目标连接的关联
    db = QSqlDatabase();
    // 再移除数据库连接
    QSqlDatabase::removeDatabase("createRequestConnection");
    delete ui;
}

另外,如果存在多次打开CreateRequestWindow的场景,当前openDatabaseConnection会复用同一个连接名称,建议通过引用计数管理连接:每次打开窗口计数+1,关闭时计数-1,计数为0时再执行removeDatabase,避免提前移除仍在使用的连接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 06:14:52