Название: Qt unhanded win32 exception Отправлено: qwyllum от Май 15, 2013, 20:06 Доброго времени суток, уважаемые форумчане! С-но проблема: имеется класс, отвечающий за работу с БД, называемый DataBase. В нем есть переменная QSqlDatabase body. В классе диалога есть переменная DataBase db. Долгое время не мог понять, почему при закрытии программы выдается ошибка о неизвестном исключении с предложением открыть проект в VS 2010. Ассемблер я понимаю плохо, поэтому копаться в отладке вряд ли получится. Я методично удалял из проги все лишнее, чтобы докопаться, какая строка вызвала исключение. И вот что накопал:
При создании диалога автоматически вызывается конструктор DataBase, т.к. диалог содержит переменную этого класса. В конструкторе есть строчка Код: body = QSqlDatabase::addDatabase("QMYSQL","Connect2"); Код: DataBase::~DataBase() Название: Re: Qt unhanded win32 exception Отправлено: Majestio от Май 15, 2013, 20:41 Вот тут в третей позиции (http://g.zeos.in/?q=addDataBase конструктор) есть полезная инфа.
PS. Попробуй вынести инициализацию в метод или слот. Название: Re: Qt unhanded win32 exception Отправлено: mta88 от Май 15, 2013, 20:54 метод addDatabase закрывает все предыдущие соединения с тем же драйвером и именем
это вполне может быть причиной исключения при закрытии программа пытается что-то записать в закрытое соединение и выдает ошибку возможными решениями будут
------------------------------------------------- второй вариант: из диалога наружу каким-то образом копируется объект data или указатель на него или объект, использующий его (QSqlQuery например) при закрытии диалога этими объектами нельзя будет пользоваться (соединение закроется, указатель станет невалидным и т.д.) Название: Re: Qt unhanded win32 exception Отправлено: qwyllum от Май 15, 2013, 20:56 Вот тут в третей позиции (http://g.zeos.in/?q=addDataBase конструктор) есть полезная инфа. Спасибо за ответ!PS. Попробуй вынести инициализацию в метод или слот. Для информации Вам: выдача результатов в поисковике на разных компьютерах может быть разной и зависит от предыдущих запросов. Поэтому я вряд ли смогу почерпнуть что-то полезное. Я вынес в отдельный метод init() подключение к БД. Результат не изменился. Название: Re: Qt unhanded win32 exception Отправлено: Majestio от Май 15, 2013, 21:03 Конец дня, телепатические способности практически на нуле! :( Давайте ваши исходники, поразбираемся.
Название: Re: Qt unhanded win32 exception Отправлено: qwyllum от Май 15, 2013, 21:04 метод addDatabase закрывает все предыдущие соединения с тем же драйвером и именем Спасибо огромное за ответ! Да, я подумал в этом направлении, но у меня всего одно соединение в БД. Тем не менее я пробовал изменить имя соединения, а потом и вовсе убрал его(в методе addDataBase предусмотрено подключение по умолчанию)это вполне может быть причиной исключения при закрытии программа пытается что-то записать в закрытое соединение и выдает ошибку второй вариант: Такого не происходит. С-но, вот все, что происходит вне диалога:из диалога наружу каким-то образом копируется объект data или указатель на него или объект, использующий его (QSqlQuery например) при закрытии диалога этими объектами нельзя будет пользоваться (соединение закроется, указатель станет невалидным и т.д.) Код: int main(int argc, char *argv[]) В классе DataBase, который создается при создании диалога прописано: Код: if (!QSqlDatabase::drivers().contains("QMYSQL")) Название: Re: Qt unhanded win32 exception Отправлено: Majestio от Май 15, 2013, 21:06 метод addDatabase закрывает все предыдущие соединения с тем же драйвером и именем Не может. Соединение просто переоткрывается. Это видно в отладочных сообщениях. Если нужно два соединения - делаем так:это вполне может быть причиной исключения Код: DataBase = QSqlDatabase::addDatabase("QPSQL","First"); Название: Re: Qt unhanded win32 exception Отправлено: qwyllum от Май 15, 2013, 21:11 Конец дня, телепатические способности практически на нуле! :( Давайте ваши исходники, поразбираемся. Код: //database.h main создает сам QT, так что его нет смысла выкладывать :) Название: Re: Qt unhanded win32 exception Отправлено: thechicho от Май 15, 2013, 21:16 <QDebug>// библиотека для вывода системных сообщений
комменты жгут) это же просто класс :) Название: Re: Qt unhanded win32 exception Отправлено: Majestio от Май 15, 2013, 21:18 попробуйте вызывать init() не напрямую, а вот так:
QTimer::singleShot(2000,this,SLOT(init())); предварительно объявите его как public slots Название: Re: Qt unhanded win32 exception Отправлено: qwyllum от Май 15, 2013, 21:24 попробуйте вызывать init() не напрямую, а вот так: Спасибо за ответ! Я попробовал так, но безрезультатно. Также я создал слот close() и в деструкторе DataBase вызвал аналогичным образом его. Ошибка все равно выдается, но что странно - раньше он мне предлагал отловить исключение в Visual Studio, а теперь просто выдает окно ошибки. Ну хоть какие-то изменения :-)QTimer::singleShot(2000,this,SLOT(init())); предварительно объявите его как public slots Название: Re: Qt unhanded win32 exception Отправлено: thechicho от Май 15, 2013, 21:28 я не силен в плюсах, но
class Dialog : public QDialog { Q_OBJECT DataBase db; public: может стоить написать так class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = 0); ~Dialog(); DataBase db; //private: //DataBase db; Название: Re: Qt unhanded win32 exception Отправлено: qwyllum от Май 15, 2013, 21:33 UPD: решил поэксперементировать и в конструкторе написал так:
Код: init(); Код: QTimer::singleShot(2000,this,SLOT(init())); Не выдает ошибок и все корректно. Отсюда вывод - получается при уничтожении экземпляра диалога как-то соединение некорректно закрывается? Название: Re: Qt unhanded win32 exception Отправлено: Majestio от Май 15, 2013, 21:40 Проверено электроникой!
Testo.pro Код: #------------------------------------------------- main.cpp Код: #include "dialog.h" dialog.h Код: #ifndef DIALOG_H dialog.cpp Код: #include "dialog.h" Название: Re: Qt unhanded win32 exception Отправлено: qwyllum от Май 15, 2013, 21:41 может стоить написать так Спасибо за ответ! К сожалению, не помоглоclass Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = 0); ~Dialog(); DataBase db; //private: //DataBase db; Название: Re: Qt unhanded win32 exception Отправлено: Majestio от Май 15, 2013, 21:43 А теперь напишу как правильно делать) Только схожу выкурю сигару 8)
Название: Re: Qt unhanded win32 exception Отправлено: thechicho от Май 15, 2013, 21:49 Dialog::~Dialog()
{ delete ui; db.close(); } а так Название: Re: Qt unhanded win32 exception Отправлено: qwyllum от Май 15, 2013, 21:52 Проверено электроникой! Спасибо! Ваша программа работает без ошибок. Но в диалоге содержится объект QSqlDatabase, тогда как у меня это отдельный класс. В перспективе там будет куча методов обращения к БД. Поэтому остался главный вопрос - что в моем коде не так? Эх, пойду заварю чай и продолжу копать) Название: Re: Qt unhanded win32 exception Отправлено: qwyllum от Май 15, 2013, 21:59 Dialog::~Dialog() Спасибо! Реально, огромное спасибо) программа больше не выдает ошибок. Одно странно, я думал, что Qt должен сам завершать соединение при уничтожении переменной. Но век живи, век учись :){ delete ui; db.close(); } а так Название: Re: Qt unhanded win32 exception Отправлено: Majestio от Май 15, 2013, 22:06 1) Из проекта убираете все неработающее, связанное с БД.
2) В проект добавляете это myglobal.h и myglobal.cpp myglobal.h Код: #ifndef MYGLOBAL_H myglobal.cpp Код: #include "myglobal.h" 3) Во всех модулях, где нужно обращение к БД прописываете #include "myglobal.h". Это даст возможность обращаться с статическому экземпляру класса вот так: Код: Global.DbHost = "192.168.1.123"; Помните - обращение к этому всему делать строго из любого слота. Чтобы соединение пошло автоматом после открытия диалога - слот по синглшоту вы уже знаете как вызывать. Название: Re: Qt unhanded win32 exception Отправлено: thechicho от Май 15, 2013, 22:10 чтобы Qt удалял, надо парента указывать.
при удалении парента, вызывается деструктор объекта. DataBase db(this); а в деструкторе уже DataBase::~DataBase() { body.close(); } хотя я в теории не особо силен, поэтому не уверен, что сработает. попробуйте Название: Re: Qt unhanded win32 exception Отправлено: Majestio от Май 15, 2013, 22:31 А вообще в духе расовой чистоты считаю что QSqlDatabase обязательно нужно выносить в глобальную статическую переменную. Это даст:
1) возможность обращения к "хэндлу" БД из любого виджета приложения 2) мотивацию не заниматься созданиями/уничтожениями "хэндлов" БД без очевидной необходимости 3) возможность управления множеством БД (если такое требуется) из любого виджета приложения Правда в таком случае нужно подпилить напильником типа этого: QMap <QString, QSqlDatabase*> MyClaster; Вот тогда имеет смысл динамически управлять экземплярами QSqlDatabase. Название: Re: Qt unhanded win32 exception Отправлено: thechicho от Май 15, 2013, 22:45 //QSqlDatabase обязательно нужно выносить в глобальную статическую переменную
имеется в виду этот объект? MyGlobal Global; почему он статический? по поводу глобального класса для доступа к бд, хз. у тс отдельный класс для работы с бд. создает объект бд, когда надо. так удобнее по идее. хотя мой опыт работы с бд заканчивается на единичном подключении к бд стандартными методами кьют, без вспомогательных классов. Название: Re: Qt unhanded win32 exception Отправлено: Old от Май 15, 2013, 23:00 А вообще в духе расовой чистоты считаю что QSqlDatabase обязательно нужно выносить в глобальную статическую переменную. Это даст: Да почитайте вы уже документацию по этому классу. :)Не нужно ничего никуда выносить. Он сам предоставляет кучу методов для доступа к соединению из любого места программы. Название: Re: Qt unhanded win32 exception Отправлено: Majestio от Май 15, 2013, 23:09 имеется в виду этот объект? MyGlobal Global; почему он статический? Статические экземпляры класса создаются сразу же после старта приложения (не дожидаясь, к примеру создания экземпляра главного окна). Это гарантирует то, что к моменту создания любого виджета есть набор общих переменных, видимость которых должна быть глобальной. по поводу глобального класса для доступа к бд, хз. у тс отдельный класс для работы с бд. создает объект бд, когда надо. так удобнее по идее. Представим сценарий многопользовательской работы с БД. 1) С "моим" подходом - подключился к БД в начале "сеанса" работы, отключился в конце. Как минимум это дает возможность "спросить" БД, а сколько и кто именно сейчас в онлайне. 2) С динамическими подключениями, отключениями ... а смысл создавать и уничтожать "хэндлы"? На это же уходит дополнительное время, как минимум. 3) С неглобальным хранением "хэндлов" БД ... а кому отдать владение? И главное зачем его потом делать глобально видимым ... а еще не забыть его проинициализировать вовремя... Ну вот как-то так. ЗЫ: Сейчас я свое приложение оформляю в виде DLL с отложенной загрузкой. В dll-ке вообще несколько "главных" окон (инициализируемых интерфейсов), кто из них главнее? :P Название: Re: Qt unhanded win32 exception Отправлено: Majestio от Май 15, 2013, 23:14 Да почитайте вы уже документацию по этому классу. :) Не нужно ничего никуда выносить. Он сам предоставляет кучу методов для доступа к соединению из любого места программы. Милейший, у меня приложение поднимает два соединения. Одно работает с транзакциями и блокировками. Второе - регистрирует операции в базе (кто залочил, когда, кто удалил, и пр ...). Второе нужно для того, чтобы эти операции можно было проводить во время открытой и еще незавершенной транзакции (первого соединения). Поэтому я остаюсь при свое точке зрения, со всем уважением ;) Название: Re: Qt unhanded win32 exception Отправлено: Old от Май 15, 2013, 23:20 Милейший, у меня приложение поднимает два соединения. Одно работает с транзакциями и блокировками. Второе - регистрирует операции в базе (кто залочил, когда, кто удалил, и пр ...). Второе нужно для того, чтобы эти операции можно было проводить во время открытой и еще незавершенной транзакции (первого соединения). Поэтому я остаюсь при свое точке зрения, со всем уважением ;) Это нужно исключительно вам исключительно для этого приложения, не находите?Так почему вы рекомендуете это для всех и всегда? В большинстве случаев это избыточно и хватает функционала предоставляемого самим QSqlDatabase. А про статические объекты/переменные не писал только ленивый. Чем меньше их будет у вас программе, тем проще ее будет сопровождать в дальнейшем. Название: Re: Qt unhanded win32 exception Отправлено: Majestio от Май 15, 2013, 23:34 Это нужно исключительно вам исключительно для этого приложения, не находите? Так почему вы рекомендуете это для всех и всегда? В большинстве случаев это избыточно и хватает функционала предоставляемого самим QSqlDatabase. 1) Ваш вариант - QSqlDatabase::database("MyDB") 2) Мой вариант - Global.MyDB Я, как минимум, экономлю электричество на написание лишних на 19 символов, как максимум - на отсутствии необходимости Qt бессмысленного поиска "MyDB" в списке зарегистрированных соединений. А про статические объекты/переменные не писал только ленивый. Чем меньше их будет у вас программе, тем проще ее будет сопровождать в дальнейшем. Мало ли кто чего писал ;D ... Лично у меня только одна - MyGlobal. И в ней все глобальной видимости. Не понимаю, зачем изобретать овальные колеса - если круглое и так ниче. Название: Re: Qt unhanded win32 exception Отправлено: Old от Май 15, 2013, 23:36 Не понимаю, зачем изобретать овальные колеса - если круглое и так ниче. А это дело времени и масштаба проекта... Поймете. ;)Название: Re: Qt unhanded win32 exception Отправлено: thechicho от Май 15, 2013, 23:37 //Статические экземпляры класса создаются сразу же после старта приложения (не дожидаясь, к примеру создания экземпляра главного окна). Это гарантирует то, что к моменту создания любого виджета есть набор общих переменных, видимость которых должна быть глобальной.
может под статической переменной вы имеете в виду переменную, созданную в стеке? согласно http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9_%D0%BA%D0%BB%D0%B0%D1%81%D1%81 переменную (объект класса) MyGlobal Global; нельзя назвать статической, т.к. не каждая функция класса статическая (их вообще нет). то есть глобальная переменная - да глобальная статическая переменная - нет или я что-то не так понимаю? если не трудно, скиньте ссылку, где вы прочитали, что статические экземпляры класса создаются сразу же после старта приложения Название: Re: Qt unhanded win32 exception Отправлено: thechicho от Май 15, 2013, 23:44 //2) Мой вариант - Global.MyDB
вы привели не полный класс? нет же поля MyDB class MyGlobal { public: QString DbHost; QString DbName; QString DbUser; QString DbPass; QSqlDatabase DataBase; MyGlobal(); bool OpenDB(); }; Название: Re: Qt unhanded win32 exception Отправлено: Majestio от Май 15, 2013, 23:52 В моем варианте (в том, который приводил) - Global.DataBase;
Название: Re: Qt unhanded win32 exception Отправлено: Majestio от Май 16, 2013, 00:11 переменную (объект класса) MyGlobal Global; нельзя назвать статической, т.к. не каждая функция класса статическая (их вообще нет). Увы, в приведенном мною выше примере я чутка ошибся, в черновики лазил) Правильнее так:-- myglobal.h --- extern MyGlobal Global; и -- myapp.cpp --- int main(int argc, char *argv[]) { MyGlobal Global; тогда если посмотрим вызовы конструкторов/деструкторов: Код: int main(int argc, char *argv[]) Это будет выглядеть так: MyGlobal::MyGlobal main1 main2 Dialog::Dialog main3 main4 Dialog::~Dialog MyGlobal::~MyGlobal Название: Re: Qt unhanded win32 exception Отправлено: Majestio от Май 16, 2013, 00:28 переменную (объект класса) MyGlobal Global; нельзя назвать статической, т.к. не каждая функция класса статическая (их вообще нет). Все верно - я неверно выразился. В статическом классе нет конструкторов, деструкторов и есть описатели static.то есть глобальная переменная - да глобальная статическая переменная - нет Название: Re: Qt unhanded win32 exception Отправлено: thechicho от Май 16, 2013, 13:34 ясно, спс.
а не думали синглтон для этой задачи сделать? Название: Re: Qt unhanded win32 exception Отправлено: Majestio от Май 16, 2013, 21:16 а не думали синглтон для этой задачи сделать? Синглтон привнесет только дополнительный код, но чего-то существенного не улучшит в данном вопросе. По большому счету можно вообще обойтись без объявления класса, а завернуть это в namespace (для многопоточного доступа наверное лучше все ж как экземпляр класса). Цель же этого всего - только централизация общедоступных ресурсов.Название: Re: Qt unhanded win32 exception Отправлено: qwyllum от Май 17, 2013, 23:19 1) Из проекта убираете все неработающее, связанное с БД. 2) В проект добавляете это myglobal.h и myglobal.cpp Огромное спасибо за пример. Ваш пример пригодился немного для другого - позволил уменьшить количество методов в диалоге) Что касается исключения - иногда программа генерировала исключения, иногда нет. Я переустановил винду и ошибка исчезла сама собой. Прошу прощения у всех, что отнял Ваше время. |