LINUX.ORG.RU

[Qt] ругань на удаление QSqlDatabase

 


0

0

Интерфейс к базе данных у меня реализован в виде синглтона, у которого есть приватный член QSqlDatabase dbase;

Так вот, при инициализации и работе все ок, но при удалении в консоли появляется ругань -

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

Погуглив, я решил, что нужно делать базе close() перед удалением, но как только я не извращался с закрытием - ставил на atexit(), подключал слот к сигналу destroyed() QApplication, вручную вызывал блин в обработчике закрытия, все равно ворнинг не исчезает. Кто-нибудь сталкивался с подобным?

★★★★★

У меня тоже синглтон. Столкнулся c такой же фигней. В рассылке нашел:

В деструкторе надо сделать:

m_pProjectManager->db = QSqlDatabase();
m_pProjectManager->db.close();
Fastman
()
Ответ на: комментарий от lester_dev

У меня подозрение что ты не один раз открываешь коннект. Вот как у меня это примерно организованно:

class CProjectManager : public QObject
{
	Q_OBJECT
public:

	static  CProjectManager *Instance()
	{
		if(self == NULL)
			self = new CProjectManager();
		return self;
	}
	void FreeInst()
	{
		if(self == this)
			delete this;
		self = NULL;
	}
	static CProjectManager *GetPrjMng()
	{
		return self;
	}

public:

        bool    DBCreate();



protected:
	CProjectManager();
	~CProjectManager();

private:
	static CProjectManager *self;
        QSqlDatabase    db;
....
bool CProjectManager::DBConnect()
{
	db = QSqlDatabase::addDatabase("QSQLITE", "DBName");
	db.setDatabaseName(qApp->applicationDirPath() +    QDir::separator() + QString("somedb.db"));
	bool bOK = db.open();

	#ifdef QT_DEBUG
		qDebug() << "DB connect:"<< bOK; 
	#endif
	
	return bOK;
}
Fastman
()
Ответ на: комментарий от Fastman
static  CProjectManager *Instance()
{
    if(self == NULL)
        self = new CProjectManager();
    return self;
}

Опасный синглтон

mannaz
()
Ответ на: комментарий от Fastman

Не, открывается один раз, дело в другом - деструктор вызывается позже, чем база пытается закрыться. Вот такой вот коленкор.

lester_dev ★★★★★
() автор топика
Ответ на: комментарий от lester_dev

Instance() - ом он просто строиться. Наприемер сразу при запуске приложения в конструкторе что то типа: m_pProjectManager = CProjectManager::Instance();

А уже в последующих случаях:

bool bExist = CProjectManager::GetPrjMng()->DBFileExist(clFIlelist.at(i), cFullPath);

Fastman
()
Ответ на: комментарий от Fastman

так никто (нормальный) не делает. GetPrjMng фтопку, Instance-ом получать экземпляр достаточно.

и, да, кстати,
>Опасный синглтон

+1

Q_ASSERT бы добавить перед return self;

xydo ★★
()
Ответ на: комментарий от Fastman
static  CProjectManager *Instance()
   {
      if(self == NULL)
         self = new CProjectManager();
      return self;
   }

За такие синглтоны надо бить по пальцам. Статические данные + статические методы != Синглтон.

yoghurt ★★★★★
()
Ответ на: комментарий от xydo

Хм, только что обнаружил, что у моего синглтона нет макроса Q_OBJECT. Добавил - ld падает с

/usr/bin/ld: Dwarf Error: Offset (19439) greater than or equal to .debug_str size (4787).

Все чудесатее и чудесатее

lester_dev ★★★★★
() автор топика
Ответ на: комментарий от xydo
int main()
{
    QApplication a(argc, argv);
    MainWindow w;
...
    w.show();
    QObject::connect(&a, SIGNAL(aboutToQuit()), &w, SLOT(aboutToQuit()));
...
}


void MainWindow::aboutToQuit()
{
	Global::Db::instance().aboutToQuit();
}

namespace Global
{
	typedef Singleton<DatabaseImpl> Db;
}

void DatabaseImpl::aboutToQuit()
{
	dbase = QSqlDatabase();
	dbase.close();
}

Итог: нихрена. Что еще не так? Вызывать через MainWindow пришлось из-за падения линкера от присутствия макроса Q_OBJECT в синглтоне.

lester_dev ★★★★★
() автор топика
Ответ на: комментарий от lester_dev

В доках вот что написано:

The correct way to do it:

{
QSqlDatabase db = QSqlDatabase::database("sales");
QSqlQuery query("SELECT NAME, DOB FROM EMPLOYEES", db);
}
// Both "db" and "query" are destroyed because they are out of scope
QSqlDatabase::removeDatabase("sales"); // correct


т.е, если создаешь экземпляр QSqlDatabase как элемент своего класса, то делать ему removeDatabase в деструкторе нельзя, ибо он будет удален _после_ вызова removeDatabase, на это у тебя и варнинги. Я в таком случае делал просто: перед удалением класса-обертки соединения спрашивал как называется его экземпляр QSqlDatabase (connectionName()), запоминал и после удаления делал removeDatabase() для имени свежеудаленного экземпляра.
Может это и не правильно, но помогло. Варнинги пропали и проблемы под виндой тоже.

driver8
()
Ответ на: комментарий от driver8

>запоминал и после удаления делал removeDatabase() для имени свежеудаленного экземпляра.

вот это немного не понял, у меня обертка удаляется в статическом деструкторе, ибо синглтон. Блин, может нафиг хранить экземпляр QSqlDatabase в синглтоне? Он мне нужен только чтобы модели создавать и распихивать по видам.

lester_dev ★★★★★
() автор топика

Я нашел в чем проблема! Нашел! У меня модели хранятся в хеше, чтоб не плодить экземпляры одних и тех же таблиц, так я забыл этот хеш подчистить, позор на мои седины. Все решилось элементарно:

	QHash<QString, QAbstractItemModel*>::iterator it = models.begin();
	do
	{
		qDebug() << "deleting model " << it.key();
		delete it.value();
	} while (++it != models.end());
lester_dev ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.