Crash-Segmentation fault
-
Let me see if I can somehow make this clear. I have a mainwindow widget with a stacked widget. Each stack of the stacked widget is a class that is loaded when the mainwindow is constructed. I have a combo box on two of the stacked widgets that I need to sychronize.
The problem seems to be that the pointer to the ui class of the second stacked widget gets lost (this is my guess, maybe not even a good guess).In the class for the second stacked widget, I can access the ui classes and manipulate them sucessfully until I call this from the other stacked widget, then I get the segmentation fault. The method gets called sucessfully but it seems like the pointer to the method gets lost. The method can be called sucessfully from mainwindow widget but when called from namepage widget it creates the segmentation fault.
Here is the relevant code:
mainwindow.cpp
@#include <QtSql>
#include <QSqlError>
#include <QDebug>
#include <QtGui>
#include "namepage.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "database.h"
#include "projectpage.h"MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
name=new NamePage(this);
project = new ProjectPage(this);
ui->MainStackWidget->setCurrentIndex(0);
ui->MainStackWidget->addWidget(name);
ui->MainStackWidget->addWidget(project);
readSettings(); //this reads the last used id from the names in the databasevoid MainWindow::readSettings()
{
QSettings settings ("QT Test","Project Manager");
int indexId=settings.value("lastName",0).toInt();
name->restoreName(indexId);
project->restoreName(indexId); //this call here works!
}
}@
namepage.cpp
@#include <QtGui>
#include <QtSql>
#include "namepage.h"
#include "ui_namepage.h"
#include "projectpage.h"NamePage::NamePage(QWidget *parent) :
QWidget(parent),
ui(new Ui::NamePage)
{
ui->setupUi(this);
}void NamePage::restoreName(int id)
{
if (id>=0)
{
int index = ui->cmbName->findData(id);
ui->cmbName->setCurrentIndex(index);
}
else
{
ui->cmbName->setCurrentIndex(0);
}
}
void NamePage::on_cmbName_currentIndexChanged()
{
project->restoreNameCombo(ui->cmbName->itemData(ui->cmbName->currentIndex()).toInt());//this call will create segmentation fault.
}@
projectpage.cpp
@#include <QDate>
#include <QtGui>
#include <QtSql>
#include <QDebug>
#include "projectpage.h"
#include "ui_projectpage.h"
#include "namepage.h"ProjectPage::ProjectPage(QWidget *parent) :
QWidget(parent),
ui(new Ui::ProjectPage)
{
ui->setupUi(this);
name=new NamePage;
ui->lblDate->setText(QDate::currentDate ().toString());//this ui class reference works
updateNameComboBox();
}
void ProjectPage::updateNameComboBox()
{QSqlQuery query; //all appropriate references were previously implemented not shown for brevity query.exec("SELECT id,LName, FName FROM name"); ui->cmbSecName->blockSignals(true); ui->cmbSecName->clear();
while (query.next())
{
ui->cmbSecName->addItem(query.value (2).toString()+ " "
+ query.value (1).toString(),query.value (0).toInt());
ui->cmbSecName->blockSignals(false);}// the above ui methods work
}
void ProjectPage::restoreNameCombo(int cmbId) //this is where the problem lies
//if called from mainwindow it works, if called from namepage, it creates a segmentation fault
{
if (cmbId>=0)
{
int cmbIndex=ui->cmbSecName->findData(cmbId);
ui->cmbSecName->setCurrentIndex(cmbIndex);
}
else
{
ui->cmbSecName->setCurrentIndex(0);
}
}@
What is the problem? -
Can you post your namepage.h? maybe you forgot to instantiate the project variable. I don't see it being constructed on the constructor either.
-
In method NamePage::on_cmbName_currentIndexChanged() you call on member project. This seems not to be initialized.
I assume this should hold a pointer to the project member of your MainWindow class. This is not true, as you never set this variable in NamePage and it is not automatically assigned from the value of MainWindow (why should it be?).
Also, you should strongly consider using your own signals and slots to change the other combobox. NamePage should know nothing about the internals of ProjectPage and vice versa. It is generally considered wrong programming style in Qt to directly manipulate the controls of one widget class from another one.
-
Here is my namepage.h
@#ifndef NAMEPAGE_H
#define NAMEPAGE_H
#include <QWidget>
class ProjectPage;namespace Ui {
class NamePage;
}class NamePage : public QWidget
{
Q_OBJECTpublic:
explicit NamePage(QWidget *parent = 0);
~NamePage();
void restoreName(int);
int getLastName();private:
Ui::NamePage *ui;
NamePage *name;
ProjectPage *project;
void updateNameComboBox();};
#endif // NAMEPAGE_H@
Do you see anything wrong here? I think the pointer is a valid one?
Gerolf, I created another NamePage object because I was going to pass some information from the projectpage to the namepage...I think I will change that to use signals and slots.
I think I will change the code to use signals and slots as soon as I get some free time.
Volker, I am still trying to figure out the signals and slots syntax to address one class to another. I will try to change this!
I really appreciate all of your assistance. -
You're very lucky it crashed. No, really.
We've had an incident some time ago: one of our products (installed in about 1000 offices all over the country) started to get mad and do a strange things after some months of stable working. The problem was in uninitialized pointer of course. But it really worked fine for a while and passed through QA department, some automated stress-test and a months in a production before we had this bug in a one -happy- day.
-
Thanks for all the help! I am pretty new at C++ and Qt programming and I am reading and trying all I can to better understand. I am still a bit confused... Gerolf, you stated that if I create a new instance of NamePage, I am changing the new instance. I don't quite understand. I created a new instance for a new class. I guess this is not the correct way? And then you say that I need to pass the pointer to the existing NamePage to ProjectPage. I am not sure how to do that. Could you give me an example of how to do that?
Volker, You stated that I did not pass a pointer of ProjectPage to the NamePage and that the ProjectPage *project pointer is uninitialized. I thought that by delaring a ProjectPage class in the header of NamePage and a pointer "ProjectPage *project" in the NamePage header took care of this.
I am going to rewrite this to use signals and slots, I kinda understand how to do this between classes, so I will give it a try.
But my question now is (and this is just for knowlege in case I run accross a similiar situation) How do you go about passing pointers and would it work if I instantiate a pointer to each class in MainWindow and pass the pointer around? And what is the method to do that.
Again, Thanks for your advice and I will post back after I change the code for signals and slots and see if I can get it to work! -
Hi poporacer,
passing the pointer would solve your problem (which is a C++, not a Qt problem) or using signals / slots.
What I meant with
bq. you stated that if I create a new instance of NamePage, I am changing the new instance.
If you have
@
1 class A
2 {
3 A()
4 {
5 m_p2 = new B;
m_bNotified = false;
6 }
7 foo1()
8 {
9 m_p2->foo();
10 }
11 notify(){m_bNotified = true};
11a notified(){return m_bNotified};
11b B* m_p2;
12 }
13
14 class B
15 {
16 foo()
17 {
18 m_p3 = new A;
19 m_p3->notify();
20 }
20a A* m_p3;
21 }
22
23 main(...)
24 {
25 A* m_p1 = new A;
26 m_p1->foo1();
27 m_p1->notified(); // will return false !!!
28 }
@If you call on line 26 the instance m_p1->foo, on line 18 you create a new instance of A and the notify (line 19)will not arrive at object m_p1 but m_p3 as you have 2 instances. You do the same in your code. m_p1 != m_p3 so if you go back to main and call notified on m_p1, it will return false, as m_p3 is notified, not m_p1.
[EDIT: fixed blockquote tag, Volker]
[EDIT: added Variable types, Gerolf] -
Regarding your pointer problems, see "my answer":http://developer.qt.nokia.com/forums/viewreply/16349/ in your signals/slots thread.