Russian Qt Forum
Сентябрь 23, 2024, 16:24 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Приложение падает при emit в пользовательском классе.  (Прочитано 7850 раз)
Arceny
Гость
« : Июнь 02, 2008, 19:08 »

Есть приложение, есть свой собственный класс sql на основе QObject.

В конструкторе приложения инициализируется как db = new sql(this);

При генерации сигнала из класса emit сигнал получаю ошибку сегментации. Этот сигнал пока ещё ни к чему не подключен.

Код
where
#0  QMetaObject::activate (sender=0x0, m=0x806c208, local_signal_index=1, argv=0x0) at kernel/qobject.cpp:3076
#1  0x08069109 in sql::readCategories ()
#2  0x08066d9f in sql::deleteDisc ()
#3  0x0805f2d7 in myTree::deleteDisc ()
#4  0x08068c6d in myTree::qt_metacall ()
...
Видно что валится при вызове из функции класса.

Далее привожу весь код класса на всякий случай. Помогите, пожалуйста, найти ошибку.

Код
C++ (Qt)
#ifndef SQL_H
#define SQL_H
 
#include <QObject>
#include <QtSql>
 
struct configuration;
 
class sql : public QObject {
Q_OBJECT
public:
sql(QObject *parent = 0);
~sql();
bool isOpen();
 
signals:
void updateCategory(int catid);
void readCategories();
private:
QSqlDatabase db;
configuration * cnf;
bool checkQuery(QSqlQuery q);
public slots:
bool initDatabase();
bool openDatabase();
bool closeDatabase();
bool deleteDisc(int discid);
bool deleteCategory(int catid);
bool moveDisc(int discid, int oldid, int catid);
bool moveAllDiscs(int oldid, int catid);
bool addDisc(QString name, QString descr, int year, int catid);
//bool addDisc();
};
 
#endif

Код
C++ (Qt)
#include <QMessageBox>
 
#include "sql.h"
#include "mainwindow.h"
 
/// Класс, в который вынесен основной функционал работы с БД
 
sql::sql(QObject *parent) : QObject(parent) {
cnf = &((mainWindow*)parent)->cnf;
}
 
sql::~sql() {
 
}
 
// проверяет запрос на безошибочность
bool sql::checkQuery(QSqlQuery q) {
if ( q.lastError().type() != QSqlError::NoError ) {
QMessageBox::critical(0,QCoreApplication::applicationName(),"SQL: "+q.lastQuery()+"\nError: "+q.lastError().text());
return false;
}
return true;
}
 
bool sql::initDatabase() {
qDebug() << "sql::initDatabase()";
if(cnf->dbType=="QSQLITE") {
QFile file(cnf->dbName);
file.remove();
}
if(openDatabase()) {
QSqlQuery query;
query.exec("CREATE TABLE category ("
"id INTEGER PRIMARY KEY,"
"name VARCHAR(64) NOT NULL,"
"nth INTEGER NOT NULL,"
"items INTEGER)");
if(!checkQuery(query)) return false;
query.exec("CREATE TABLE disc ("
"id INTEGER PRIMARY KEY,"
"name VARCHAR(128) NOT NULL,"
"descr TEXT,"
"year INTEGER,"
"catid INTEGER NOT NULL,"
"FOREIGN KEY (catid) REFERENCES category)");// ON UPDATE CASCADE)");
if(!checkQuery(query)) return false;
query.exec("CREATE TABLE files ("
"id INTEGER PRIMARY KEY," // просто id записи
"name VARCHAR(1024) NOT NULL," // имя файла/директории (не путь)
"parentid INTEGER NOT NULL," // id записи родителя (директории), для верхнего уровня 0
"type INTEGER NOT NULL," // тип: директория или файл (тип файла по необходимости)
"size INTEGER NOT NULL," // размер
"date VARCHAR(20)," // дата файла, не обязательно
"metadata INTEGER," // ссылка на метаданные если нужно.
"discid INTEGER NOT NULL," // ссылка на диск к которому принадлежат файлы
"FOREIGN KEY(discid) REFERENCES disc)");
if(!checkQuery(query)) return false;
return true;
} else
return false;
}
 
bool sql::openDatabase() {
qDebug() << "sql::openDatabase()";
closeDatabase();
db = QSqlDatabase::addDatabase(cnf->dbType);
db.setDatabaseName(cnf->dbName);
db.setHostName(cnf->server);
db.setUserName(cnf->username);
db.setPassword(cnf->password);
if(!db.open()) {
QMessageBox::warning(0, tr("Database error!"), db.lastError().text());
return false;
}
return true;
}
 
bool sql::closeDatabase() {
qDebug() << "sql::closeDatabase()";
if(db.isOpen()) {
QSqlQuery q1(db);
q1.exec("VACUUM files");
q1.exec("VACUUM disc");
q1.exec("VACUUM category");
db.close();
QSqlDatabase::removeDatabase(db.connectionName()); // correct
return true;
} else
return false;
}
 
bool sql::deleteDisc(int discid) {
qDebug() << "sql::deleteDisc(int discid)";
 
QSqlQuery q;
// извлекаем id категории
q.prepare("SELECT catid FROM disc WHERE id = ?");
q.addBindValue(discid); q.exec(); q.next();
int catid = q.value(0).toInt();
 
// удаляем диск
q.prepare("DELETE FROM disc WHERE id = ?");
q.addBindValue(discid); q.exec();
 
// удаляем файлы, принадлежащие диску
q.prepare("DELETE FROM files WHERE discid = ?");
q.addBindValue(discid); q.exec();
 
// извлекаем число дисков из категории
q.prepare("SELECT items FROM category WHERE id = ?");
q.addBindValue(catid); q.exec(); q.next();
int items = q.value(0).toInt();
 
// уменьшаем число  дисков в категории на единичку
q.prepare("UPDATE category SET items = ? WHERE id = ?");
q.addBindValue(items-1); q.addBindValue(catid); q.exec();
 
emit readCategories();
 
return true;
}
 
bool sql::moveAllDiscs(int oldid, int catid) {
oldid=0; catid=0;
return true;
}
 
bool sql::moveDisc(int discid, int oldid, int catid) {
discid=0; oldid=0; catid=0;
return true;
}
 
bool sql::deleteCategory(int catid) {
qDebug() << "sql::deleteCategory(int catid)";
QSqlQuery q;
 
//удаляем диски
q.prepare("SELECT id from disc WHERE catid = ?");
q.addBindValue(catid); q.exec();
while(q.next()) {
deleteDisc(q.value(0).toInt());
}
 
// удаляем категорию
q.prepare("DELETE FROM category WHERE id=?");
q.addBindValue(catid);
q.exec();
 
return true;
}
 
bool sql::addDisc(QString name, QString descr, int year, int catid) {
return true;
}
 
bool sql::isOpen() {
return db.isOpen();
}
Записан
Alex03
Гость
« Ответ #1 : Июнь 03, 2008, 06:28 »


Rebuild All (make clean ; make) не помогает?
Записан
Arceny
Гость
« Ответ #2 : Июнь 03, 2008, 08:22 »

Нет
Кстати что любопытно. Генерация сигнала в другом методе не приводит к падению (сделал mysignal(int) некий).
Что-бы это могло быть?
« Последнее редактирование: Июнь 03, 2008, 08:34 от Arceny » Записан
Sergeich
Гость
« Ответ #3 : Июнь 03, 2008, 10:14 »

Приаттач код
Записан
Arceny
Гость
« Ответ #4 : Июнь 03, 2008, 12:53 »

Приаттач код
Всего проекта?

Прикладываю весь проект, это программа для каталогизации дисков. СУБД пока только sqlite тестировалась, соответственно при инициализации БД выбирать её.

Сигнал генерируется в методе класса sql , вызываемого при удалении диска из какой-либо категории.

З.Ы. писалось на Qt4.4 , под винду собирать не пробовал.

http://slil.ru/25858903
« Последнее редактирование: Июнь 03, 2008, 13:08 от Arceny » Записан
Sergeich
Гость
« Ответ #5 : Июнь 03, 2008, 16:32 »

Собрал VS2005 на XP SP2. Собираться не хотел, писал что не может найти метода QSqlDatabase::connectionName  Шокированный Глянул в qsqldatabase.h - действительно нету, похоже какой-то косяк у Троллей. Заменил на QSqlDatabase::databaseName - все скомпилялось.
Далее, при запуске выходил на Q_ASSERT в header()->setResizeMode(0, QHeaderView::Stretch) в myTree::myTree и filesTree::filesTree, добавил setColumnCount.
Если не выбрать текущий элемент падало myTree::deleteDisc(), на строках
Код:
QTreeWidgetItem *item = currentItem();
if(item->parent() == NULL)
где проверка item на 0!  //NULL в С++ писать не принято.
И наконец источник проблемы с сигналами - конструкция
Код:
myTree::myTree(QWidget *parent) : QTreeWidget(parent) {
//....
db = ((mainWindow*)parent)->db;
//....
}
parent в данном случае - QSplitter, а не mainWindow, в итоге в db хранится хуй знает что.
Если уж и писать такое то так:
Код:
mainWindow* mw = qobject_cast<mainWindow> parent;
if (mw)
  db = mw->db;
else
  db = 0;
Нормальное решение - либо передавать db в параметрах конструктора, либо делать синглетон, где хранить db, cnf и все остальное что может существовать в единственном экземпляре.
З.Ы. Я бы больше 3 за это поставил Улыбающийся
Записан
Sergeich
Гость
« Ответ #6 : Июнь 03, 2008, 16:45 »

Какая-то херь получилась с QSqlDatabase::connectionName() Шокированный При повторном открытии проекта он нашелся в qsqldatabase.h (открывал через VS), хотя при первом запуске он его в упор не хотел видеть, и глазами искал, и поиском - нету и все Шокированный Счас с ним скомпилялось без проблем.
Записан
Arceny
Гость
« Ответ #7 : Июнь 04, 2008, 01:58 »

Какая-то херь получилась с QSqlDatabase::connectionName() Шокированный При повторном открытии проекта он нашелся в qsqldatabase.h (открывал через VS), хотя при первом запуске он его в упор не хотел видеть, и глазами искал, и поиском - нету и все Шокированный Счас с ним скомпилялось без проблем.
А версия Qt не успела обновиться? Походу это в 4.4 ввели. И я там не совсем корректно с БД разрываю соединение.

За комментарии по коду спасибо. Щас уже чото делать нет сил, завтра (то есть сегодня) посмотрю поподробнее.

Offtop: А ещё: раз модераторы матерятся, значит и пользователям можно? :-)
Записан
Sergeich
Гость
« Ответ #8 : Июнь 04, 2008, 12:16 »

Offtop: А ещё: раз модераторы матерятся, значит и пользователям можно? :-)
Если по делу и к месту - можно Веселый
Записан
Godfather
Гость
« Ответ #9 : Июнь 04, 2008, 14:46 »

из личного опыта хочу заметить что лучше всего открывтаь БД через
Код:
QSqlDatabase::addDatabase("DRIVER", QUuid::createUuid().toString());
т.е. каждому соединению присваивать уникальный идентификатор, иначе 2ой экземпляр того же класса (при аналогичном драйвере) будет работать с тем же соединением, а не со своим, и убдет коллизия. и если первй закроет его, 2ой упадет при запросе

ну и в деструкторе я пишу
Код:
if(dbCon.isOpen()) db.Con.close();
ииначе в Debug Output ругается что соединение осталось открытым что типа нехорошо
Записан
vregess
Гость
« Ответ #10 : Июнь 04, 2008, 20:34 »

Offtop: А ещё: раз модераторы матерятся, значит и пользователям можно? :-)
Если по делу и к месту - можно Веселый
Я бы не советовал. Не педагогично.
Записан
Steven_Orko
Гость
« Ответ #11 : Июнь 05, 2008, 16:54 »

Offtop: А ещё: раз модераторы матерятся, значит и пользователям можно? :-)
Если по делу и к месту - можно Веселый

OFF: Модераторы не БОГИ. И им подражать не обязательно!!! )))
Записан
ритт
Гость
« Ответ #12 : Июнь 12, 2008, 03:18 »

офф: действительно...подражайте администраторам Улыбающийся
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.112 секунд. Запросов: 22.