Здравствуйте, использую в программе std::shared_ptr и программа начинает себя вести по странному. У меня программа БД для школы и вот при добавлении к примеру нового ученика она может, как корректно отработать так и упасть. Вот листинг добавления ученика:
class Pupil : public Models
{
private:
QString name;
QString dateOfBirth;
QString phoneNumber;
QString personalData;
QString address;
QString hisClass;
Pupil(QString &name, QString &dateOfBirth, QString &phoneNumber,
QString &personalData, QString &address, QString &hisClass);
public:
class Builder {
QString name;
QString dateOfBirth;
QString phoneNumber;
QString personalData;
QString address;
QString hisClass;
public:
Builder& setName(QString name);
// Setters ...
Pupil* build();
};
QString getPhoneNumber() const;
// Getters ...
};
...
// Здесь происходит выделение через умный указатель
Pupil *Pupil::Builder::build()
{
std::shared_ptr<Pupil> newPupil(new Pupil(name, dateOfBirth, phoneNumber, personalData, address, hisClass));
return newPupil.get();
}
...
...
void PupilsForm::clickedBtnAddPupil()
{
AddPupilDialog addPupilDialog;
if(addPupilDialog.exec() == QDialog::Accepted)
{
Pupil *pupil = addPupilDialog.getData();
pupilsModel->addItem(pupil);
}
}
...
...
Pupil *AddPupilDialog::getData()
{
Pupil *pupil = Pupil::Builder()
.setName(ui->edtName->text())
.setNumber(ui->edtPhoneNumber->text())
.setAddress(ui->edtAddress->text())
.setDateOfBirth(ui->edtDateOfBirth->text())
.setPersonalData(ui->edtPersonalData->text())
.setHisClass(ui->cbxClass->currentText())
.build();
return pupil;
}
...
...
void PupilsModel::addItem(Models *item)
{
Pupil *pupil = (Pupil*)item;
//Prepare for execute the query
QMap<QString, QString> prepareQuery;
prepareQuery.insert(":name", pupil->getName());
prepareQuery.insert(":number", pupil->getPhoneNumber());
prepareQuery.insert(":address", pupil->getAddress());
prepareQuery.insert(":personalData", pupil->getPersonalData());
prepareQuery.insert(":dateOfBirth", pupil->getDateOfBirth());
prepareQuery.insert(":class", pupil->getHisClass());
// Здесь программа не падает, выдает корректное ФИО ученика
qDebug() << pupil->getName();
//Executing the query
QString query = "INSERT INTO pupils(name, data_birth, person_data, number, address, id_class)"
"VALUES(:name, :dateOfBirth, :personalData, :number, :address, "
"(SELECT c.id FROM classses c WHERE c.name = :class))";
dataBase->execInsert(query, prepareQuery);
}
...
void DataBase::execInsert(QString &stringQuery, QMap<QString, QString> &prepareQuery)
{
QSqlQuery query;
query.prepare(stringQuery);
for(auto it = prepareQuery.begin(); it != prepareQuery.end(); it++)
{
query.bindValue(it.key(), it.value());
}
// А вот здесь как раз таки она иногда и падает с map не читаются данные
qDebug() << prepareQuery.first();
query.exec();
checkSuccessRequest(query);
}
Работает это так... Форма учеников у нее обработчик по нажатию на кнопку добавить, которые открывает диалог добавления ученика. В диалоге формируется модель ученика и если диалог успешно сработан, то данные возвращаются к форме и передаются классу для работы с моделью ученика. Там обрабатывается bind-ится поля для запросы и передаются в класс для работы с базой данных. Я вот одного только понять не могу почему иногда работает все нормально, а иногда падает, я бы понял, если бы все время падало, но... Может кто-нибудь поможет или подскажет из-за чего это,уже голову всю изломал.
Не буду копаться и ковыряться везде, скажу только об этом:
// Здесь происходит выделение через умный указатель
Pupil *Pupil::Builder::build()
{
std::shared_ptr<Pupil> newPupil(new Pupil(name, dateOfBirth, phoneNumber,
personalData, address, hisClass));
return newPupil.get();
}
Итак, создаем локальный shared_ptr
(зачем?), который на выходе из функции удаляет переданный ему объект в динамической памяти и освобождает память. Так что возвращается указатель на уже освобожденную память. Чистой воды UB.
Уж лучше б вы просто писали
Pupil *Pupil::Builder::build()
{
return new Pupil(name, dateOfBirth, phoneNumber,
personalData, address, hisClass));
}
или
std::shared_ptr<Pupil> Pupil::Builder::build()
{
std::shared_ptr<Pupil> newPupil(new Pupil(name, dateOfBirth, phoneNumber,
personalData, address, hisClass));
return newPupil;
}
Дальше просто не смотрел, этого уже вполне достаточно...
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
В первой строке входных данных содержится число N (1 <= N <= 100000)Во второй строке задается последовательность из N больших латинских букв (буквы...
Почему в следующем коде std::swap не рассматривается в качестве кандидата при вызове swap и приходится писать его полностью с пространством имён?...
А можно ли привести тип умного указателя родительского класса к дочернему? К примеру есть есть базовый класс Models и от него наследуется класс...