【问题标题】:QSqlQuery Memory issues. QSqlQuery::exec() and QSqlDatabase::open()/close();QSqlQuery 内存问题。 QSqlQuery::exec() 和 QSqlDatabase::open()/close();
【发布时间】:2011-07-14 08:18:22
【问题描述】:

我正在检查我创建的应用程序的内存使用情况。它多次调用从数据库读取值和从数据库中写入值(SQLite 3)。我观察到以下情况:

  • QSqlQuery::exec() 使用一些 KB 的 RAM 来执行给定的查询,但在超出范围后不会释放内存。

  • QSqlDatabase:: open() & close() 并不能帮助释放资源,正如文档所建议的那样。如果有的话,close() 会导致资源(至少是内存)保持“被困”在堆/堆栈上。

例如,这是我用来访问数据库的典型代码段。

QStringList values;
db.open();
QString strQuery = "SELECT DISTINCT " + field + " FROM " + table + str;

QSqlQuery query(db);
query.prepare(strQuery);

if(query.exec() == true)
{
  while(query.next())
  {
    values.push_back(query.value(0).toString());
  }
}

db.close();

经过实验,我发现下面的代码“陷阱”更少内存:

QStringList values;
QString strQuery = "SELECT DISTINCT " + field + " FROM " + table + str;

QSqlQuery query(strQuery, db);

  while(query.next())
  {
    values.push_back(query.value(0).toString());
  }

但是,仍有少量内存没有释放。有没有其他人经历过这样的事情?

我可以如何释放这段记忆吗?

附:这里也发生了同样的情况,一些内存永远不会被释放:

db.open();
QSqlQuery query(db);

query.exec("DELETE FROM table1");
query.exec("DELETE FROM table2");
query.exec("DELETE FROM table3");
query.exec("DELETE FROM table4");
...

db.close();

【问题讨论】:

    标签: c++ qt sqlite


    【解决方案1】:

    看来,为了释放这块内存,你必须创建QSqlQuery变量作为指针,并在关闭数据库之前删除这个指针:

    QStringList values;
    db.open();
    QString strQuery = "SELECT DISTINCT " + field + " FROM " + table + str;
    
    QSqlQuery *query = new QSqlQuery(db);
    query->prepare(strQuery);
    
    if(query->exec() == true)
    {
      while(query->next())
      {
        values.push_back(query->value(0).toString());
      }
    }
    
    delete query;
    db.close();
    

    在数据库关闭后释放内存。

    【讨论】:

    • 这里的内存没有被删除以进行查询。所以问题仍然与内存泄漏相同。
    【解决方案2】:

    你必须在关闭数据库之前使用QSqlQuery.finish() 或QSqlQuery.clear。否则 Query 对象中会遗漏剩余内存。文档中提到Query对象可以用于多个查询。当您查询 10,000 条记录时,您会注意到“内存泄漏”。内存使用量急剧上升。

    【讨论】:

    • finish() 或 clear() 作为删除 QSqlQuery 对象并关闭数据库的“解决方案”是一个更好的主意。我根本不愿意关闭数据库,删除 QSqlQuery 对象根本没有释放内存。只有完成清除资源。而且由于我使用了非常胖的 select 语句,这使我的程序的内存使用量减少了一半。
    【解决方案3】:

    从 QSqlDatabase::addDatabase 和 QSqlDatabase::database() 的文档中可以推断出有一个管理数据库连接的全局变量。如果你查看 qsqldatabase.cpp,你会发现一个 QConnectionDict。

    顺便说一句:不要通过连接字符串来构造 SQL 查询,如果查询的某些部分有可能来自用户输入,请始终使用 prepare 和 bindValue(SQL 注入!)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-01
      • 2013-05-27
      • 2020-03-12
      • 2012-03-21
      • 1970-01-01
      • 1970-01-01
      • 2018-03-11
      相关资源
      最近更新 更多