PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Kleiner Segfault mit QStrings



axeljaeger
22-10-2003, 12:42
Hi,
ich wollte in einem größeren Programm das Erstellen von mehreren gleichartigen Widgets durch eine Widgetfactory lösen, leider kommt es dabei zu einem Speicherzugriffsfehler, den ich mir nicht erklären kann: (Ist eine kleine Beispielapp, der Fehler dürfte aber der gleiche sein)


#include <qwidget.h>
#include <qstringlist.h>
#include <qvbox.h>
#include <qpushbutton.h>
#include <qapplication.h>

class Factory
{
public:
QStringList keys() const { return QStringList() << "QPushButton"; }
QWidget* create(const QString & key, QWidget* parent = 0, const char* name = 0)
{
if(key == "QPushButton")
return new QPushButton("PushButton",parent, name);
return 0;
}
};


class MainWindow : public QVBox
{
public:
MainWindow();
};

MainWindow::MainWindow() : QVBox(0)
{
Factory* factory = new Factory();

for(QStringList::Iterator it = factory->keys().begin(); it != factory->keys().end(); ++it)
factory->create(*it, this);

delete factory;
}

int main(int argc, char** argv)
{
QApplication app(argc, argv);
MainWindow mw;
app.setMainWidget(&mw);
mw.show();
return app.exec();
}


Dabei kommt es zu folgenden merkwürdigen Fehlern:

Starting program: /home/axel/Documents/factory
[New Thread 16384 (LWP 2653)]



Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 16384 (LWP 2653)]
0x4050c95e in operator==(QString const&, char const*) ()
from /usr/lib/qt3/lib/libqt-mt.so.3
Current language: auto; currently c
(gdb) bt
#0 0x4050c95e in operator==(QString const&, char const*) ()
from /usr/lib/qt3/lib/libqt-mt.so.3
#1 0x40012780 in environ () from /lib/ld-linux.so.2
#2 0x0804b802 in MainWindow (this=0xbffff510) at factory.cpp:31
#3 0x0804b889 in main (argc=1, argv=0xbffff654) at factory.cpp:39
#4 0x407827f7 in __libc_start_main () from /lib/i686/libc.so.6
(gdb)


In meinem großen Programm hab ich noch lustigere Sachen entdeckt, unter anderem Segfaults in QMotifStyle, was ich noch nie angefasst habe

anda_skoa
22-10-2003, 14:45
Dein Problem liegt hier:



for(QStringList::Iterator it = factory->keys().begin(); it != factory->keys().end(); ++it)
factory->create(*it, this);


factory->keys() gibt jedes mal eine neue Kopie einer StringList zurück.
Das temporäre return Objekt gilt nur bis zum Ende des Statements, hier also zB nur bei der Iteratorinitialisierung, aber nicht merh im Schleifenbody.

Außerdem sind die Iteratoren sind nur in einer Instanz eines Containers stabil.

Zwei Lösungsmöglichkeiten:



private:
QStringList keylist;
public:
Factory() { keylist << "QPushButton"; }
const QStringList& keys() const { return keylist; }

// ...

for(QStringList::ConstIterator it = factory->keys().begin(); it != factory->keys().end(); ++it)
factory->create(*it, this);

Also mit const Reference und festem Listen Objekt oder einfacher mit lokalem Zwischenobjekt:


QStringList keys = factory->keys();
for(QStringList::Iterator it = keys.begin(); it != keys.end(); ++it)
factory->create(*it, this);


Ciao,
_

axeljaeger
22-10-2003, 15:04
Hm, hab ich jetzt auch gemerkt. In der Doku von Trolltech steht auch: "You should make a copy". Ich hab die zweite Lösung gemacht und es funktioniert.