QSqlQuery Проблемы с памятью.QSqlQuery :: exec () и QSqlDatabase :: open () / close (); - PullRequest
4 голосов
/ 14 июля 2011

Я проверяю использование памяти приложением, которое я сделал. Он делает многочисленные вызовы для чтения и записи значений в базу данных и из нее (SQLite 3). Я заметил следующее:

  • QSqlQuery :: exec () использует некоторый КБ ОЗУ для выполнения данного запроса, но не освобождает память после того, как он выходит из области видимости.

  • 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());
  }

Однако небольшой объем памяти все еще не освобожден. Кто-нибудь еще испытывал что-либо подобное?

Могу я как-нибудь освободить эту память?

P.s. То же самое происходит и здесь, часть памяти никогда не освобождается:

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();

Ответы [ 3 ]

3 голосов
/ 18 июля 2011

Кажется, что для освобождения этой памяти вы должны создать переменную 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();

Затем память освобождается после закрытия базы данных.

1 голос
/ 05 сентября 2011

Вы должны использовать QSqlQuery.finish () или QSqlQuery.clear, прежде чем закрыть базу данных. В противном случае остаточная память остается в объекте Query. В документе упоминается, что объект Query можно использовать для множественного запроса. Вы заметите «утечку памяти» .. когда вы запросите 10000 записей. Использование памяти резко возрастает.

1 голос
/ 14 июля 2011

Из документации QSqlDatabase :: addDatabase и QSqlDatabase :: database () можно сделать вывод, что существует глобальная переменная, которая управляет соединениями с базой данных.Если вы заглянете в qsqldatabase.cpp, то обнаружите QConnectionDict.

Кстати: не создавайте запросы SQL путем объединения строк, всегда используйте prepare и bindValue (SQL-инъекция!), Если есть вероятность, что частизапрос поступает от пользователя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...