PDA

View Full Version : Memory Trouble



nimrod
5th February 2006, 21:55
This is my first major project using Qt, and I have a bit of a problem.
I subclassed QMainWindow for my program, and got the layout and menus to work.
The layout is made of QSplitters and in the main view I have a QWidgetStack.
I wanted to keep the widget stack id's in integer variables, so I added two variables in the class definition,and tried:

widgetStackItemId=mainview->id(wigetPointer);

And later used:

mainview->raiseWidget(widgetStackItemId);

Now, this worked with one of the variables, but as soon as I tried using another variable, it started giving me segmentation faults.
At first, I thought it was related to the QWidgetStack, but it seems that as soon as I assign a value to the second variable (can be just a number), the program crashes with a seg fault.
I think I made a mistake with a pointer, but I don't know which one. Here is a code based on my real code. I changed variable and function names, and shortened some boring bits (menu items). The code works like that, I think the bug is a matter of scale.

Header (mymainwindow.h):




#ifndef MYMAINWINDOW_H
#define MYMAINWINDOW_H

#include <qmainwindow.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qsplitter.h>
#include <qlistbox.h>
#include <qtable.h>
#include <qscrollview.h>
#include <qwidgetstack.h>
#include <qstringlist.h>
#include <qtextedit.h>


class MyMainWindow: public QMainWindow
{
Q_OBJECT
public:
MyMainWindow(QWidget *parent=0,const char *name=0);
protected:
//CloseEvent is called whenever the user closes the program's window.
void CloseEvent(QCloseEvent *event);

private slots:
bool mnuFileQuit();
void mnuViewItem();

void leftPane1Changed();
private:

void initLayout();
void initMenus();

void createMainWidget1();
void createMainWidget2();

QSplitter *mainsplitter;
QSplitter *leftsplitter;
QWidgetStack *mainview;
QListBox *leftPane1;
QListBox *leftPane2;

//id's in the widget stack:
int widgetstackid1;
int widgetstackid2;

//Now actual menu items (rather than their functions) are defined:
QPopupMenu *fileMenu;
QPopupMenu *viewMenu;
};
#endif



Implementation:



#include "mymainwindow.h"
#include <qapplication.h>

MyMainWindow::MyMainWindow(QWidget *parent,const char *name):QMainWindow(parent,name){
widgetstackid1=0;
widgetstackid2=0; //In the real program, this line causes a seg fault.

initLayout();
initMenus();
}
void MyMainWindow::initLayout(){
mainsplitter=new QSplitter(Qt::Horizontal,this);
setCentralWidget(mainsplitter);

leftsplitter=new QSplitter(Qt::Vertical,mainsplitter);
leftPane1=new QListBox(leftsplitter);
leftPane1->insertItem("Item 0");
leftPane1->insertItem("Item 1");

connect(leftPane1,SIGNAL(currentChanged ( QListBoxItem * )),this,SLOT(leftPane1Changed()));
leftPane2=new QListBox(leftsplitter);

mainview=new QWidgetStack(mainsplitter);

createMainWidget1();
createMainWidget2();
}

void MyMainWindow::initMenus(){
fileMenu=new QPopupMenu (this);
viewMenu=new QPopupMenu(this);

fileMenu->insertItem("&Quit",this,SLOT(mnuFileQuit()));


viewMenu->insertItem("View Menu Item",this,SLOT(mnuViewItem()));

menuBar()->insertItem("&File",fileMenu);
menuBar()->insertItem("&View",viewMenu);
}

void MyMainWindow::createMainWidget1(){
QTable *mainWidget1Table = new QTable( 4, 2, mainview );
mainWidget1Table->setLeftMargin(0);
mainWidget1Table->setReadOnly(true);
QStringList labels;
labels.append("col 1");
labels.append("col 2");

int i;
for(i=0;i<2;i++){
mainWidget1Table->setColumnWidth(i,60);
}
mainWidget1Table->setColumnLabels(labels);
mainWidget1Table->setSorting(true);

mainview->addWidget(mainWidget1Table);

widgetstackid1=mainview->id(mainWidget1Table);
}

void MyMainWindow::createMainWidget2(){
QTextEdit *mainWidget2Text;
mainWidget2Text=new QTextEdit(mainview);
mainWidget2Text->setReadOnly(true);
mainWidget2Text->setText("<h1>hello</h1>world.");
mainview->addWidget(mainWidget2Text);
widgetstackid2=mainview->id(mainWidget2Text); //In the real program, this line causes a seg fault.
}

//Menu functions
void MyMainWindow::mnuViewItem(){
qWarning("mnuViewItem() called.");
}
bool MyMainWindow::mnuFileQuit(){
return (close(true));
}


void MyMainWindow::leftPane1Changed(){
int currentItem=leftPane1->currentItem();
switch(currentItem){
case 0:
mainview->raiseWidget(widgetstackid1);
break;
case 1:
mainview->raiseWidget(widgetstackid2);
break;
}
}

//Main program
int main(int argc,char *argv[]){
QApplication app(argc,argv);
MyMainWindow windowThing;
app.setMainWidget(&windowThing);
windowThing.show();

return app.exec();
}

jacek
5th February 2006, 22:28
It does not crash on my system. Try running "make clean && make.

The only problem is with this method:
bool MyMainWindow::mnuFileQuit(){
return (close(true));
}
You tell the widget created on a stack to autodestruct itself, which leads to double delete. Use close() method without any parameters.

Codepoet
5th February 2006, 22:59
Another idea would be to try a memory debugger like valgrind: Compile your program in debug mode and then
valgrind --tool=memcheck path/to/executable

nimrod
5th February 2006, 23:03
Recompiling everything did solve the problem.
Still worried about instability, though. I'll see what happens later.

Thanks for the tip about closing.

Mariane
6th February 2006, 19:45
If you think you have memory leaks, my tip would be to try SEVERAL
checks. I usually use electric fence (CFLAGS = -O2 -g -lefence in Makefile)
and LeakCheck (command line once you've downloaded the file). But not
both at the same time. They catch different things, but if you try to use them
both at the same time they interfere with one another.

Mariane