Précédent   Forum des professionnels en informatique > C et C++ > Bibliothèques > Qt
Qt Forum d'entraide technique sur la bibliothèque Qt. Avant de poster -> F.A.Q Qt
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 11/01/2012, 22h13   #1
Membre éclairé
 
Avatar de TNT89
 
Inscription : juillet 2007
Messages : 288
Détails du profil
Informations personnelles :
Âge : 22

Informations forums :
Inscription : juillet 2007
Messages : 288
Points : 308
Points : 308
Par défaut QDialog et ses dérivées provoquent des SEGFAULT

Bonjour à tous,

J'ai un problème très ennuyeux avec Qt. J'avais l'habitude de passer par des appels statiques dans le syle des suivantes:
Code :
1
2
3
QString filename = QFileDialog::getOpenFileName(NULL, tr("Load a file"), ".", "*.*");
// ou
QMessageBox::information(this, tr("Error!"), error.what());
Malheureusement, avec ma nouvelle configuration, ces appels provoquent un SEGFAULT. Pour le QFileDialog, j'obtient avec GDB :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#0 0x7ffff57bc12f	??() (/lib/x86_64-linux-gnu/libc.so.6:??)
#1 0x7ffff4d1475c	XSetCommand() (/usr/lib/x86_64-linux-gnu/libX11.so.6:??)
#2 0x7ffff4d194bb	XSetWMProperties() (/usr/lib/x86_64-linux-gnu/libX11.so.6:??)
#3 0x7ffff70aeec5	QWidgetPrivate::create_sys(this=0x6d4f50, window=27263364, initializeWindow=true, destroyOldWindow=118) (kernel/qwidget_x11.cpp:799)
#4 0x7ffff70605e2	QWidget::create(this=0x7c5210, window=0, initializeWindow=true, destroyOldWindow=true) (kernel/qwidget.cpp:1467)
#5 0x7ffff706ae8a	QWidget::setVisible(this=0x7c5210, visible=<optimized out>) (kernel/qwidget.cpp:7596)
#6 0x7ffff74c66ec	QDialog::setVisible(this=0x7c5210, visible=<optimized out>) (dialogs/qdialog.cpp:739)
#7 0x7ffff74c5490	show(this=0x7c5210) (../../include/QtGui/../../src/gui/kernel/qwidget.h:487)
#8 (	QDialog::exec(this=<optimized out>) (dialogs/qdialog.cpp:543)
#9 0x408180	Interface::openFile() () (??:??)
#10 0x4088ef	Interface::loadPipeline() () (??:??)
#11 0x409b24	Interface::qt_metacall(QMetaObject::Call, int, void**) () (??:??)
#12 0x7ffff6aebb1a	QMetaObject::activate(sender=0x685f40, m=<optimized out>, local_signal_index=<optimized out>, argv=0x0) (kernel/qobject.cpp:3278)
#13 0x7ffff73c5f21	QAbstractButtonPrivate::emitReleased(this=<optimized out>) (widgets/qabstractbutton.cpp:574)
#14 0x7ffff73c712c	QAbstractButtonPrivate::click(this=0x779c90) (widgets/qabstractbutton.cpp:537)
#15 0x7ffff73c73ac	QAbstractButton::mouseReleaseEvent(this=0x685f40, e=0x7fffffffda20) (widgets/qabstractbutton.cpp:1121)
#16 0x7ffff7067016	QWidget::event(this=0x685f40, event=0x7fffffffda20) (kernel/qwidget.cpp:8259)
#17 0x7ffff70169f4	notify_helper(e=0x7fffffffda20, receiver=0x685f40, this=0x680c70) (kernel/qapplication.cpp:4467)
#18 (	QApplicationPrivate::notify_helper(this=0x680c70, receiver=0x685f40, e=0x7fffffffda20) (kernel/qapplication.cpp:4439)
#19 0x7ffff701c17b	QApplication::notify(this=<optimized out>, receiver=0x685f40, e=0x7fffffffda20) (kernel/qapplication.cpp:4028)
#20 0x7ffff6ad8fbc	QCoreApplication::notifyInternal(this=0x680c40, receiver=0x685f40, event=0x7fffffffda20) (kernel/qcoreapplication.cpp:731)
#21 0x7ffff70179c2	sendEvent(event=<optimized out>, receiver=<optimized out>) (../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:215)
#22 (	QApplicationPrivate::sendMouseEvent(receiver=0x685f40, event=0x7fffffffda20, alienWidget=0x0, nativeWidget=0x685f40, buttonDown=0x0, lastMouseReceiver=..., spontaneous=true) (kernel/qapplication.cpp:3127)
#23 0x7ffff7093de8	QETWidget::translateMouseEvent(this=0x685f40, event=<optimized out>) (kernel/qapplication_x11.cpp:4465)
#24 0x7ffff7092bea	QApplication::x11ProcessEvent(this=0x680c40, event=0x7fffffffe140) (kernel/qapplication_x11.cpp:3591)
#25 0x7ffff70bad32	x11EventSourceDispatch(s=0x685eb0, callback=0, user_data=0x0) (kernel/qguieventdispatcher_glib.cpp:146)
#26 0x7ffff45d50cf	g_main_context_dispatch() (/lib/x86_64-linux-gnu/libglib-2.0.so.0:??)
#27 0x7ffff45d58c8	??() (/lib/x86_64-linux-gnu/libglib-2.0.so.0:??)
#28 0x7ffff45d5a99	g_main_context_iteration() (/lib/x86_64-linux-gnu/libglib-2.0.so.0:??)
#29 0x7ffff6b03abf	QEventDispatcherGlib::processEvents(this=0x682210, flags=<optimized out>) (kernel/qeventdispatcher_glib.cpp:422)
La structure de l'application est assez simple : une classe Application dérivant de QApplication et possedant un pointeur vers une classe Interface dérivant de QWidget. Les appels sont réalisés depuis des fonctions "public slots" et appelés par un évènement (QPushButton::released()).

J'ai donc essayé sans les appels statiques avec le code suivant :
Code :
1
2
3
4
5
6
7
QPointer<QFileDialog> dlg = new QFileDialog(this);
dlg->setFileMode(QFileDialog::ExistingFile);
dlg->setOption(QFileDialog::DontUseNativeDialog, true); //J'ai essayé ce drapeau avec les appels statiques sans plus de succès
dlg->selectNameFilter("*.ppl");
dlg->exec(); //ou dlg->show();
//exploitation...
delete dlg;
Et j'obtiens la même erreur... SAUF quand j'appelle cette fonction sans passer "par un évènement" mais en la lançant à la main directement à la fin du constructeur de Interface par exemple. En fait, tant que je n'ai pas appellé la fonction exec() de QApplication, tout va bien.

Je pense donc, très fortement pour une mauvaise configuration de mon système :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
uname -a
Linux *** 3.1.0-1-amd64 #1 Fri Dec 23 16:37:11 UTC x86_64 GNU/Linux
g++ -v
gcc version 4.6.2 (Debian 4.6.2-11)
make -v
GNU Make 3.81
qmake -v
QMake version 2.01a
Using Qt version 4.7.3 in /usr/lib
dbus-daemon --version
D-Bus Message Bus Daemon 1.2.24
Xorg -version
X.Org X Server 1.11.2.902 (1.11.3 RC 2)
Release Date: 2011-12-09
Le truc c'est que je n'utilise pas Gnome mais seulement un compositeur : Compiz-GTK...

Enfin, un code minimal pour reproduire l'erreur :
Interface.hpp :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifndef __TEST_INTERFACE__
#define __TEST_INTERFACE__
 
	#include <iostream>
	#include <QApplication>
	#include <QWidget>
	#include <QPushButton>
	#include <QVBoxLayout>
	#include <QFileDialog>
	#include <QMessageBox>
        #include <QPointer>
 
	// Object
		class Interface : public QWidget
		{
			Q_OBJECT
 
			private :
				QVBoxLayout* 	layout;
				QPushButton	*chPpl;
 
			public :
				Interface(void);
 
			public slots :
				void loadFile(void);
				void openFile(void);
		};
 
		class Application : public QApplication
		{
			Q_OBJECT
 
			private :
				Interface	*interface;
 
			public :
				Application(int argc, char** argv);
		};
 
#endif
Interface.cpp :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include "interface.hpp"
// Src :
	Interface::Interface(void)
	{
		chPpl	= new QPushButton("Load a file", this);
		layout 	= new QVBoxLayout(this);
		layout->addWidget(chPpl);
		QObject::connect(chPpl,		SIGNAL(released()), this, SLOT(openFile()));
		setGeometry(1000, 100, 800, 700);
		show();
                // Si j'appelle ici, openFile() ou loadFile(), les deux fonctionnent!
	}
 
	void Interface::openFile(void)
	{
                // L'appel suivant provoque le SEGFAULT
		QString filename = QFileDialog::getOpenFileName(NULL, tr("Load a file"), ".", "*.*", NULL, QFileDialog::DontUseNativeDialog);
 
		if(!filename.isEmpty())
		{
			std::cout << "Loading : " << filename.toUtf8().constData() << std::endl;
		}
	}
 
	void Interface::loadFile(void)
	{
		std::cout << "Loading GUI..." << std::endl;
		openFile(); // Provoque le SEGFAULT
		std::cout << "...end GUI" << std::endl;
 
                // Loading file
	}
 
	Application::Application(int argc, char** argv)
	 : QApplication(argc,argv)
	{
		interface = new Interface;
                // Si j'appelle d'ici interface->loadFile() ou interface->openFile(), ils fonctionnent!
	}
main.cpp :
Code :
1
2
3
4
5
6
7
8
9
10
 
#include "interface.hpp"
 
int main(int argc, char** argv)
{
	std::cout << "Test interface..." << std::endl;
 
	Application* a = new Application(argc, argv);
	return a->exec();
}
interface.pro (avec ou sans debug) :
Code :
1
2
3
4
5
CONFIG 		+= 	qt debug
INCLUDEPATH  	+= 	/usr/local/lib
HEADERS      	+= 	interface.hpp
SOURCES      	+= 	main.cpp \
			interface.cpp
Je suis preneur de toutes les idées!

Vous remerciant,
TNT89 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/01/2012, 06h13   #2
Membre éclairé
 
Avatar de TNT89
 
Inscription : juillet 2007
Messages : 288
Détails du profil
Informations personnelles :
Âge : 22

Informations forums :
Inscription : juillet 2007
Messages : 288
Points : 308
Points : 308
Etape 1 :
Etape 2 :

Quand on est bête il faut lire la doc... Et notamment http://developer.qt.nokia.com/doc/qt...l#QApplication qui stipule bien avec un beau Warning, qu'il faut que argv et argc soient valides pour la durée de vie de QApplication.

Du coup la correction est simple, il faut passer argc par référence et pas par copie (sinon la copie est détruite après la fin du constructeur et la mémoire peut-être réutilisée... ce qui à mon avis engendre la lecture d'arguments fictifs dans argv, notamment des arguments interprêtés comme des instructions de taille pour le serveur X dans mon cas, je n'ai aucune idée de pourquoi j'arrive à faire fonctionner ce code avec Gnome d'installé, et le reproduire sur plusieurs systèmes).

Dans interface.hpp et interface.cpp, on doit remplacer les lignes correspondante par :
Code :
Application(int& argc, char** argv)
Et miracle... vous connaissez la suite!

(merci)
TNT89 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 23h06.


 
 
 
 
Partenaires

Hébergement Web