OK, I will explain. The reason your code is crashing is because you have declared your member variable widgets directly, as QWidget instances, rather than as pointers to QWidget instances. Memory is being corrupted in the MainWindow destructor because the member variables are destroyed by C++ before the MainWindow instance is destroyed. However, because in Qt, these child widgets are owned by the MainWindow, Qt is trying to destroy them a second time (through the Qt parent-child relationship, which is responsible for destroying them), after C++ has already destroyed them. The memory they used to occupy is gone, and so you get a crash because Qt is trying to access an object that no longer exists. (It could be happening the other way around - Qt destroys them first, and then C++ tries to do it again, but it's the same effect).
This has nothing to do with arguments about whether it is better to use heap vs. stack in any particular situation. It is entirely about Qt's parent-child ownership hierarchy of QObjects and who is in charge of the child objects' lifetimes.
So the solution to your problem is pretty simple:
1. Change every one of your QWidget-based member variables in MainWindow to "QWidget *".
2. In the constructor for MainWindow, call the "new" operator to create the QWidget instances
3. Use these widgets through the pointer operator (->)
// MainWindow.h
// Change #1:
private:
GlWidget * glWidgetWindow;
BuiltSphere * built_sphere_window;
BuiltCylinder * built_cylinder_window;
EditObject * edit_object_window;
// MainWindow.h
// Change #1:
private:
GlWidget * glWidgetWindow;
BuiltSphere * built_sphere_window;
BuiltCylinder * built_cylinder_window;
EditObject * edit_object_window;
QComboBox * builder_select;
QStackedWidget * builder_stacked_widget;
QTabWidget * tab_widget_01;
To copy to clipboard, switch view to plain text mode
// MainWindow.cpp:
{
// Change #2:
glWidgetWindow = new GlWidget( this );
built_sphere_window = new BuiltSphere( this );
// etc.
// Change #3:
glWidgetWindow->setFixedSize( 1024, 768 );
// etc.
// MainWindow.cpp:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
// Change #2:
glWidgetWindow = new GlWidget( this );
built_sphere_window = new BuiltSphere( this );
// etc.
// Change #3:
glWidgetWindow->setFixedSize( 1024, 768 );
// etc.
To copy to clipboard, switch view to plain text mode
In general, you should never declare QWidget-based member variables as QWidget, but always as QWidget *. (Actually, anything QObject-based).
The only places you should use QWidget directly are these (and maybe a few other similar cases):
1. In a method where the QWidget is in scope only for the life of the method, such as posting a dialog to get information from the user.
void MainWindow::showTheDialog()
{
theDialog->exec();
}
void MainWindow::showTheDialog()
{
QDialog theDialog;
theDialog->exec();
}
To copy to clipboard, switch view to plain text mode
2. For MainWindow in main.cpp:
int main( int argc, char * argv[] )
{
MainWindow w;
w.show();
return a.exec();
}
int main( int argc, char * argv[] )
{
QApplication a( argc, argv );
MainWindow w;
w.show();
return a.exec();
}
To copy to clipboard, switch view to plain text mode
In both of these cases, the QObject instances are completely contained within the scope of the method so it is safe to create them on the stack.
Bookmarks