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
相关产品推荐
相关产品推荐

