在做一个Qt项目时,遇到几个作用域问题,很简单,但是使用的时候容易犯低级错误:
- 隐含对象QSqlDatabase::database() 作用域问题:
在使用QSqlDatabase::removeDatabase(connectionName)时,只对当前连接释放了,但是database还有引用,就会提示警告,当前连接还在,因此一般使用时,在使用database处加上作用域,执行完之后自动释放,再只需要removeDatabase即可。
QString connectionName;
{
QSqlDatabase db = DBUtil::instance()->openDataBase(QStringLiteral("%1").arg(quintptr(QThread::currentThreadId()))); // 自己封装的DBUtil
connectionName = db.connectionName();
QSqlQuery query(db);
QString sql = QString(;
try
{
if (query.exec(sql))
{
while (query.next())
{
//读取数据
}
}
else
{
qDebug() << db.lastError().text();
return false;
}
}
catch (...) {
qDebug() << db.isOpen();
}
} // 加上作用域,隐含对象QSqlDatabase::database()被删除
//释放数据库连接
QSqlDatabase::removeDatabase(connectionName);
- 更傻的问题:在子线程A中定义局部变量(一个线程类B),结果导致B中死活报错,一些设定的成员变量获取不到内存。。。
DBHeartbeatThread dbheart; // 错误的写法就是把这个实例对象放在了下面的线程里面定义
std::thread startup([&] {
while (redis_check_loop)
{
QThread::sleep(5);
if (!redis_conn) // redis未连接
continue;
/* 获取数据库连接字段 */
QJsonObject dbobject = RedisManager::instance()->getJsonObject("DBsettings");
if (dbobject.count() == 0)
continue;
/* 数据库连接心跳检测 */
DBHeartbeatThread::ConnectParam cp;
cp.ip = dbobject.value("dbhost").toString();
cp.port = dbobject.value("dbport").toInt();
cp.dbName = dbobject.value("dbname").toString();
cp.password = dbobject.value("dbpwd").toString();
cp.userName = dbobject.value("dbusername").toString();
// DBHeartbeatThread dbheart; //错误将线程实例写在了这里!!!导致dbheart里的ConnectParam 报获取内存错误,在startup线程执行完后,dbheart就被析构了,所以内存出错
dbheart.setDBTypeAndConnectParm(dbobject.value("dbtype").toString(), cp);
dbheart.start();
/* end数据库连接心跳检测 */
/* end 获取数据库连接字段 */
break; // 因为这里加了break的,所以startup线程会执行完后析构
}
});
- 数据库连接问题:
对于多线程数据库连接问题,如果用相同连接名,可能会导致冲突,可以加锁或者连接名每次不同,用完之后释放掉。