PDA

View Full Version : QT 4.1.1/X11/QTopia Core : seg fault after sub-classing QMainWindow



jlarsj
22nd February 2006, 04:14
Hi all,

I am currently writing a GUI based application using QT4.1.1. This app will run on X11 and Embedded environments ( using Qtopia Core ).

I am using QT Designer to draw all the app GUI, and I use a QMainWindow as a base for the whole app.

During my development I noticed I was getting seg faults when I was using a QFileWindow. More precisly, the built-in functions provided by QFileWindow ( create dir, erase dir,... ) accessible by the buttons cause EVERY time seg fault when the buttons are hit.

so let me show here a custom implementation I wrote to make that bug appening:

ui_MainWindow.h is autogenerated by QTDesigner then uic:


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QMainWindow>
#include <QtGui/QMenuBar>
#include <QtGui/QPushButton>
#include <QtGui/QStatusBar>
#include <QtGui/QWidget>

class Ui_MainWindow
{
public:
QWidget *centralwidget;
QPushButton *pushButton;
QMenuBar *menubar;
QStatusBar *statusbar;

void setupUi(QMainWindow *MainWindow)
{
MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
MainWindow->resize(QSize(800, 600).expandedTo(MainWindow->minimumSizeHint()));
centralwidget = new QWidget(MainWindow);
centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
pushButton = new QPushButton(centralwidget);
pushButton->setObjectName(QString::fromUtf8("pushButton"));
pushButton->setGeometry(QRect(300, 170, 87, 26));
MainWindow->setCentralWidget(centralwidget);
menubar = new QMenuBar(MainWindow);
menubar->setObjectName(QString::fromUtf8("menubar"));
menubar->setGeometry(QRect(0, 0, 800, 26));
MainWindow->setMenuBar(menubar);
statusbar = new QStatusBar(MainWindow);
statusbar->setObjectName(QString::fromUtf8("statusbar"));
statusbar->setGeometry(QRect(0, 581, 800, 19));
MainWindow->setStatusBar(statusbar);
retranslateUi(MainWindow);

QMetaObject::connectSlotsByName(MainWindow);
} // setupUi

void retranslateUi(QMainWindow *MainWindow)
{
MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0, QApplication::UnicodeUTF8));
pushButton->setText(QApplication::translate("MainWindow", "PushButton", 0, QApplication::UnicodeUTF8));
Q_UNUSED(MainWindow);
} // retranslateUi

};

namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui

#endif // MAINWINDOW_H

here my implementation files:


// main.cpp

#include "CLr4kds.h"

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
CLr4kds lr4kds;
return app.exec();
}


// CLr4kds.h

#ifndef CLR4KDS_H
#define CLR4KDS_H

#include <QApplication>
#include <QWidget>
#include <QMessageBox>
#include <QObject>
#include <QDialog>
#include <QtGui>

#include "ui_MainWindow.h"

class CLr4kds : public QMainWindow, public Ui::MainWindow
{
Q_OBJECT

public:
CLr4kds();

private:
QMainWindow *window;

public slots:

virtual void saveAs ();
};


#endif //CLR4KDS


// CLr4kds.cpp

#include "CLr4kds.h"

CLr4kds::CLr4kds ()
{
window = new QMainWindow;
this->setupUi ( window );

// CUSTOM CONNECTIONS
connect ( this->pushButton, SIGNAL ( clicked () ), this, SLOT ( saveAs () ) );

window->showMaximized ();

}

void CLr4kds::saveAs ()
{
QString ret = QFileDialog::getSaveFileName( this );
}

This very simple example, has been compiled on diffrent machines with different release of QT 4.1. The error is always the same :

- launch the app
- click on the unique button, a save dialogbox will pop up
- create a directory with the builtin function/button
- try to erase that directory with a right click on it and "Delete"

the app should quit if you do that.

So if someone can tell me where is my mistake when I subclass QMainWindow it would be great.

high_flyer
22nd February 2006, 08:40
I don't understand why do you have a QMainWindow inside a QMainWindow...
This is bad design IMHO.

Also you use :
connect ( this->pushButton, SIGNAL ( clicked () ), this, SLOT ( saveAs () ) );
And I think you mean:
connect ( window->pushButton, SIGNAL ( clicked () ), this, SLOT ( saveAs () ) );

jlarsj
22nd February 2006, 13:57
Hi High_flyer,

thanx for the answer. I modified my short example, and I still have the exact issue:



#ifndef UI_MAINWINDOW_H
#define UI_MAINWINDOW_H

#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QMainWindow>
#include <QtGui/QMenuBar>
#include <QtGui/QPushButton>
#include <QtGui/QStatusBar>
#include <QtGui/QWidget>

class Ui_MainWindow
{
public:
QWidget *centralwidget;
QPushButton *pushButton;
QMenuBar *menubar;
QStatusBar *statusbar;

void setupUi(QMainWindow *MainWindow)
{
MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
MainWindow->resize(QSize(800, 600).expandedTo(MainWindow->minimumSizeHint()));
centralwidget = new QWidget(MainWindow);
centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
pushButton = new QPushButton(centralwidget);
pushButton->setObjectName(QString::fromUtf8("pushButton"));
pushButton->setGeometry(QRect(300, 170, 87, 26));
MainWindow->setCentralWidget(centralwidget);
menubar = new QMenuBar(MainWindow);
menubar->setObjectName(QString::fromUtf8("menubar"));
menubar->setGeometry(QRect(0, 0, 800, 26));
MainWindow->setMenuBar(menubar);
statusbar = new QStatusBar(MainWindow);
statusbar->setObjectName(QString::fromUtf8("statusbar"));
statusbar->setGeometry(QRect(0, 581, 800, 19));
MainWindow->setStatusBar(statusbar);
retranslateUi(MainWindow);

QMetaObject::connectSlotsByName(MainWindow);
} // setupUi

void retranslateUi(QMainWindow *MainWindow)
{
MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0, QApplication::UnicodeUTF8));
pushButton->setText(QApplication::translate("MainWindow", "PushButton", 0, QApplication::UnicodeUTF8));
Q_UNUSED(MainWindow);
} // retranslateUi

};

namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui

#endif // UI_MAINWINDOW_H





// CMainWindow.h

#ifndef CMAINWINDOW_H
#define CMAINWINDOW_H

#include <QApplication>
#include <QWidget>
#include <QMessageBox>
#include <QObject>
#include <QDialog>
#include <QtGui>

#include "ui_MainWindow.h"


class CMainWindow : public QMainWindow
{
Q_OBJECT

public:
CMainWindow();
~CMainWindow();

private:
Ui_MainWindow ui;

public slots:

void saveAs ();
};


#endif // CMAINWINDOW





// CMainWindow.cpp

#include "CMainWindow.h"

CMainWindow::CMainWindow ()
{
ui.setupUi ( this );

// CUSTOM CONNECTIONS
connect ( ui.pushButton, SIGNAL ( clicked () ), this, SLOT ( saveAs () ) );


}

CMainWindow::~CMainWindow ()
{}



void CMainWindow::saveAs ()
{
QString ret = QFileDialog::getSaveFileName( this );
}






// main.cpp

#include "CMainWindow.h"

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
CMainWindow lr4kds;
lr4kds.show();
app.exec ();

return 0;
}

wysota
22nd February 2006, 14:32
What does the debugger say? Do dialogs in standard Qt apps (like Designer, examples, etc.) work properly?

Also be sure to call the base class constructor in the constructor of your subclass.

jpn
22nd February 2006, 15:01
Without analyzing your code any further, I wanna ask you to test if you can reproduce the same error with as simple code as this:



#include <QtGui>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFileDialog::getSaveFileName();
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
return a.exec();
}

jlarsj
22nd February 2006, 15:13
Hi,

Excuse my english, maybe I was not clear here.

What I am trying to do is to design the whole GUI with designer, generate a header file from the .ui file and sub class that header in another class to add custom SLOTS and processes.

So, I dont want to make any modification to the header generated by UIC.

My problem is that I dont find anywhere the proper way to sub-class QMainWindow, apparently.

To answer you questions:

- yes, it does work properly with Dialog
- the debugger refers to : QDirModelPrivate::restorePersistentIndexes () this is where it stops

By the way, if you use the "Trolltech" way for QMainWindow, ie the "application" example in the "examples" dir from the QT source, and open a "save as" dialog, it works !!!!

But once again, I need the sub classing approach, since I need to keep a way of maintaining my GUI with designer, I dont want to mess with the header file comming from the UIC.

So if you have an idea, I am really lost with that ....

wysota
22nd February 2006, 15:42
- the debugger refers to : QDirModelPrivate::restorePersistentIndexes () this is where it stops

What about the rest of the call stack?

And did you correct your code by calling the superclass constructor?


CMainWindow::CMainWindow () : QMainWindow(0)
{
ui.setupUi ( this );
connect ( ui.pushButton, SIGNAL ( clicked () ), this, SLOT ( saveAs () ) );
}

jlarsj
22nd February 2006, 15:51
Hi,

here is the output of the stack after crashing :



ASSERT: "persistent.indexes.count() == savedPaths.count()" in file itemviews/qdirmodel.cpp, line 1332

Program received signal SIGABRT, Aborted.
[Switching to Thread 16384 (LWP 25879)]
0x40bf67c1 in kill () from /lib/libc.so.6
(gdb) bt
#0 0x40bf67c1 in kill () from /lib/libc.so.6
#1 0x40a9f771 in pthread_kill () from /lib/libpthread.so.0
#2 0x40a9fa7b in raise () from /lib/libpthread.so.0
#3 0x40bf6554 in raise () from /lib/libc.so.6
#4 0x40bf7a88 in abort () from /lib/libc.so.6
#5 0x4092cc33 in qt_message_output (msgType=QtFatalMsg,
buf=0xbfff97a0 "ASSERT: \"persistent.indexes.count() == savedPaths.count()\" in file itemviews/qdirmodel.cpp, line 1332") at global/qglobal.cpp:1895
#6 0x4092d0c7 in qFatal (msg=0x40a0f6e0 "ASSERT: \"%s\" in file %s, line %d") at global/qglobal.cpp:2111
#7 0x4092c7ed in qt_assert (assertion=0x406040c0 "persistent.indexes.count() == savedPaths.count()", file=0x40603f97 "itemviews/qdirmodel.cpp",
line=1332) at global/qglobal.cpp:1660
#8 0x40588cf2 in QDirModelPrivate::restorePersistentIndexes (this=0x80b01a0) at itemviews/qdirmodel.cpp:1332
#9 0x40586b18 in QDirModel::refresh (this=0x80ad1b0, parent=@0xbfffb8c0) at itemviews/qdirmodel.cpp:948
#10 0x40587c51 in QDirModel::rmdir (this=0x80ad1b0, index=@0xbfffb910) at itemviews/qdirmodel.cpp:1138
#11 0x40524449 in QFileDialogPrivate::deleteCurrent (this=0x80afe00) at dialogs/qfiledialog.cpp:1428
#12 0x4052a34b in QFileDialog::qt_metacall (this=0x80ad528, _c=InvokeMetaMethod, _id=18, _a=0xbfffbe80) at moc_qfiledialog.cpp:144
#13 0x409ece67 in QMetaObject::activate (sender=0x80bc748, from_signal_index=5, to_signal_index=6, argv=0xbfffbe80) at kernel/qobject.cpp:2670
#14 0x409ed0ba in QMetaObject::activate (sender=0x80bc748, m=0x4062c0c0, from_local_signal_index=1, to_local_signal_index=2, argv=0xbfffbe80)
at kernel/qobject.cpp:2717
#15 0x401b54b5 in QAction::triggered (this=0x80bc748, _t1=false) at moc_qaction.cpp:183
#16 0x401b4c7d in QAction::activate (this=0x80bc748, event=Trigger) at kernel/qaction.cpp:894
#17 0x4048ea2e in QMenuPrivate::activateAction (this=0x80c3770, action=0x80bc748, action_e=Trigger) at widgets/qmenu.cpp:662
#18 0x40492e0c in QMenu::mouseReleaseEvent (this=0xbfffca00, e=0xbfffc4f0) at widgets/qmenu.cpp:1703
#19 0x4020b025 in QWidget::event (this=0xbfffca00, event=0xbfffc4f0) at kernel/qwidget.cpp:4965
#20 0x4049320d in QMenu::event (this=0xbfffca00, e=0xbfffc4f0) at widgets/qmenu.cpp:1770
#21 0x401c0011 in QApplicationPrivate::notify_helper (this=0x804cd78, receiver=0xbfffca00, e=0xbfffc4f0) at kernel/qapplication.cpp:3125
#22 0x401bee52 in QApplication::notify (this=0xbfffebf0, receiver=0xbfffca00, e=0xbfffc4f0) at kernel/qapplication.cpp:2855
#23 0x401c21fc in QCoreApplication::sendSpontaneousEvent (receiver=0xbfffca00, event=0xbfffc4f0) at qcoreapplication.h:174
#24 0x40220a37 in QETWidget::translateMouseEvent (this=0xbfffca00, event=0xbfffc800) at kernel/qapplication_x11.cpp:3517
#25 0x4021e574 in QApplication::x11ProcessEvent (this=0xbfffebf0, event=0xbfffc800) at kernel/qapplication_x11.cpp:2701
#26 0x40237430 in QEventDispatcherX11::processEvents (this=0x80516c0, flags={i = 20}) at kernel/qeventdispatcher_x11.cpp:112
#27 0x409d5a8c in QEventLoop::processEvents (this=0xbfffc980, flags={i = 20}) at kernel/qeventloop.cpp:124
#28 0x409d5b79 in QEventLoop::exec (this=0xbfffc980, flags={i = 0}) at kernel/qeventloop.cpp:164
#29 0x404919d2 in QMenu::exec (this=0xbfffca00, p=@0xbfffc9c8, action=0x0) at widgets/qmenu.cpp:1479
#30 0x40523d1c in QFileDialogPrivate::showContextMenu (this=0x80afe00, pos=@0xbfffd540) at dialogs/qfiledialog.cpp:1365
#31 0x4052a303 in QFileDialog::qt_metacall (this=0x80ad528, _c=InvokeMetaMethod, _id=15, _a=0xbfffcf98) at moc_qfiledialog.cpp:141
#32 0x409ece67 in QMetaObject::activate (sender=0x80bd470, from_signal_index=4, to_signal_index=4, argv=0xbfffcf98) at kernel/qobject.cpp:2670
#33 0x409ed06e in QMetaObject::activate (sender=0x80bd470, m=0x4062d2f4, local_signal_index=0, argv=0xbfffcf98) at kernel/qobject.cpp:2708
#34 0x4020fae4 in QWidget::customContextMenuRequested (this=0x80bd470, _t1=@0xbfffd540) at moc_qwidget.cpp:312
#35 0x4020b8b6 in QWidget::event (this=0x80bd470, event=0xbfffd530) at kernel/qwidget.cpp:5115
#36 0x4045f92e in QFrame::event (this=0x80bd470, e=0xbfffd530) at widgets/qframe.cpp:609
#37 0x404e462b in QAbstractScrollArea::viewportEvent (this=0x80bd470, e=0xbfffd530) at widgets/qabstractscrollarea.cpp:471
#38 0x4054440f in QAbstractItemView::viewportEvent (this=0x80bd470, event=0xbfffd530) at itemviews/qabstractitemview.cpp:949
#39 0x404e4fae in QAbstractScrollAreaPrivate::viewportEvent (this=0x80bd490, e=0xbfffd530) at widgets/qabstractscrollarea.cpp:93
#40 0x404e2fbf in QAbstractScrollAreaViewport::event (this=0x8096d70, e=0xbfffd530) at widgets/qabstractscrollarea.cpp:105


And, I did modify my code to call the superclass constructor.

high_flyer
22nd February 2006, 15:59
What is this?:
QFileDialog::getSaveFileName( this );

here is the definition of QFileDialog::getSaveFileName():

QString QFileDialog::getSaveFileName ( const QString & startWith = QString::null, const QString & filter = QString::null, QWidget * parent = 0, const char * name = 0, const QString & caption = QString::null, QString * selectedFilter = 0, bool resolveSymlinks = TRUE )
As you can see, no room for 'this', unless you do:
QFileDialog::getSaveFileName( QString::null,QString::null,this );
Try to call it with out any parameters, and see what happens.

jlarsj
22nd February 2006, 16:09
Allright,

In the online doc : http://doc.trolltech.com/4.1/qfiledialog.html#getSaveFileName

here is the definition :

QString QFileDialog::getSaveFileName ( QWidget * parent = 0, const QString & caption = QString(), const QString & dir = QString(), const QString & filter = QString(), QString * selectedFilter = 0, Options options = 0 ) [static]

And, yes I tried without any argument, still EXACTly the same results.

jlarsj
22nd February 2006, 16:43
Ok, I rewrote my code using the multiple inheritance approach, here is the code :



#ifndef UI_MAINWINDOW_H
#define UI_MAINWINDOW_H

#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QMainWindow>
#include <QtGui/QMenuBar>
#include <QtGui/QPushButton>
#include <QtGui/QStatusBar>
#include <QtGui/QWidget>

class Ui_MainWindow
{
public:
QWidget *centralwidget;
QPushButton *pushButton;
QMenuBar *menubar;
QStatusBar *statusbar;

void setupUi(QMainWindow *MainWindow)
{
MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
MainWindow->resize(QSize(800, 600).expandedTo(MainWindow->minimumSizeHint()));
centralwidget = new QWidget(MainWindow);
centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
pushButton = new QPushButton(centralwidget);
pushButton->setObjectName(QString::fromUtf8("pushButton"));
pushButton->setGeometry(QRect(300, 170, 87, 26));
MainWindow->setCentralWidget(centralwidget);
menubar = new QMenuBar(MainWindow);
menubar->setObjectName(QString::fromUtf8("menubar"));
menubar->setGeometry(QRect(0, 0, 800, 26));
MainWindow->setMenuBar(menubar);
statusbar = new QStatusBar(MainWindow);
statusbar->setObjectName(QString::fromUtf8("statusbar"));
statusbar->setGeometry(QRect(0, 581, 800, 19));
MainWindow->setStatusBar(statusbar);
retranslateUi(MainWindow);

QMetaObject::connectSlotsByName(MainWindow);
} // setupUi

void retranslateUi(QMainWindow *MainWindow)
{
MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0, QApplication::UnicodeUTF8));
pushButton->setText(QApplication::translate("MainWindow", "PushButton", 0, QApplication::UnicodeUTF8));
Q_UNUSED(MainWindow);
} // retranslateUi

};

namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui

#endif // UI_MAINWINDOW_H





// CMainWindow.h

#ifndef CMAINWINDOW_H
#define CMAINWINDOW_H

#include <QApplication>
#include <QWidget>
#include <QMessageBox>
#include <QObject>
#include <QDialog>
#include <QtGui>

#include "ui_MainWindow.h"


class CMainWindow : public QMainWindow, private Ui::MainWindow
{
Q_OBJECT

public:
CMainWindow( QWidget *parent = 0 );

public slots:

void saveAs ();
};


#endif // CMAINWINDOW





// CMainWindow.cpp

#include "CMainWindow.h"

CMainWindow::CMainWindow ( QWidget *parent ) : QMainWindow ( parent )
{
setupUi ( this );

// CUSTOM CONNECTIONS
connect ( pushButton, SIGNAL ( clicked () ), this, SLOT ( saveAs () ) );

}

void CMainWindow::saveAs ()
{
QString ret = QFileDialog::getSaveFileName ( this );
}






// main.cpp

#include "CMainWindow.h"

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
CMainWindow lr4kds;
lr4kds.show();
app.exec ();

return 0;
}



I still have the same results, I really dont get it !!!

jlarsj
22nd February 2006, 16:51
By the way, I just tried to compile this code and run it under Win32, it is working perfectly.

jacek
22nd February 2006, 18:29
I've tried the code from your second post and it works without any problems on my system (Qt 4.1.1, PLD Linux).

high_flyer
22nd February 2006, 19:30
Allright,

In the online doc : http://doc.trolltech.com/4.1/qfiledialog.html#getSaveFileName

here is the definition :

QString QFileDialog::getSaveFileName ( QWidget * parent = 0, const QString & caption = QString(), const QString & dir = QString(), const QString & filter = QString(), QString * selectedFilter = 0, Options options = 0 ) [static]

And, yes I tried without any argument, still EXACTly the same results.
You are right ofcourse, I was sure I was looking at the QT4 docs, sorry about that.

wysota
22nd February 2006, 19:44
Did you try to make clean && qmake && make your app again?

jlarsj
22nd February 2006, 20:29
Yes Wysota I did... I am a little bit lost in that, here what I found:

I have :

1) QT 4.1.1 + minGW32 on a XP SP2 machine
2) QT 4.1.1 + gcc 3.3.5 + Xfree86 on a Debian machine with 2.4.31 Kernel
3) QT 4.1.1 + gcc 3.4.5 +Xorg on a Kubuntu with 2.6.12-9 Kernel
4) QTopia core 4.1.1 + gcc 3.3.5 plus FrameBuffer driver on a Debian machine with 2.4.31 kernel

Using the code just above here are the results :

1) work perfectly, no bug
2) seg fault when trying to do a right click/ delete a directory
3) works perfectly, no bug
4) seg fault when trying to do a right click/ delete a directory

So, using 2.4.31 Kernel with gcc 3.3.5 might be the cause, I dont know its far beyond my expertise, but I think there is something incompatible between QT4.1.1/QTopia and the 2.4.31 and GCC 3.3.5.

So does someone has any idea ?

wysota
22nd February 2006, 20:38
Check Qt dependencies. Maybe it depends on an incorrect version of some library. Did you get any messages from Qt (apart from that assert statement) while the app was running? Did you compile Qt yourself or do you have it from a binary distribution? Was it compiled using the same compiler? Are you using a stable version of Qt (the one which was released today) or a daily snapshot?

jlarsj
22nd February 2006, 20:49
Did you get any messages from Qt (apart from that assert statement) while the app was running?

No, I dont get any other messages while the app is running.



Did you compile Qt yourself or do you have it from a binary distribution?

Yes, I did compile QT myself.



Was it compiled using the same compiler?

Yes



Are you using a stable version of Qt (the one which was released today) or a daily snapshot?

I am using a daily snapshot : qt-x11-opensource-src-4.1.1-snapshot-20060221

wysota
22nd February 2006, 20:51
I am using a daily snapshot : qt-x11-opensource-src-4.1.1-snapshot-20060221

Try using the stable version instead and see if the problem persists.