Speicherzugriffsfehler bei QTextEdit->setDocument()

Alles rund um die Programmierung mit Qt
Antworten
HappyEnding
Beiträge: 26
Registriert: 5. März 2009 14:15

Speicherzugriffsfehler bei QTextEdit->setDocument()

Beitrag von HappyEnding »

Hi, ich hoffe hier kann mir jemand helfen. Ich programmiere gerade an einem Widget, mit dem, nach auslesen einer .xml-Datei, eine .res-Datei generiert werden soll. Allerdings stoße ich dabei auf einen Speicherzugriffsfehler, den ich mir nicht erklaeren kann.

Der Speicherzugriffsfehler tritt in meinem Parser bei "resEdit->setDocument(document);" auf.
Der Parser wird in einem Slot aufgerufen und soll zum testen qName in den TextEdit des Widgets schreiben.

Code: Alles auswählen

/*
myparser.cpp
*/

#include <QtGui>
#include <iostream>
#include "myparser.h"

MyParser::MyParser()
	: Ui_Resmaker()
{
}

bool MyParser::startDocument()
{
	return TRUE;
}

bool MyParser::startElement(const QString&, const QString&, const QString& qName, const QXmlAttributes&)
{
	document = new QTextDocument();
	document->setPlainText(qName);

	resEdit->setDocument(document);
	return TRUE;
}

bool MyParser::endElement(const QString&, const QString&, const QString&)
{
	return TRUE;
}
Der Header dazu sieht wie folgt aus:

Code: Alles auswählen

/*
myparser.h
*/

#include <QtXml>
#include "ui_resmaker.h"

class MyParser : public QXmlDefaultHandler, public Ui_Resmaker
{
public:
	MyParser();
	bool startDocument();
	bool startElement(const QString&, const QString&, const QString&, const QXmlAttributes&);
	bool endElement(const QString&, const QString&, const QString&);
private:
	QTextDocument *document;
};
Falls die zusaetzlichen Codeteile benoetigt werden, werde ich sie posten, lasse sie aber erstmal weg, damit es nicht zu lang wird.

Ich hoffe es findet sich jemand, der mir sagen kann woran es liegt.

Danke
HappyEnding
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

setupUi(); im Konstruktor vergessen.
Übrigens solltest du private von Ui_* erben, sonst hat jeder Zugriff auf die Elemente deiner Ui, was böse enden kann.
HappyEnding
Beiträge: 26
Registriert: 5. März 2009 14:15

Beitrag von HappyEnding »

Daran hab ich auch schon gedacht, das setupUi() existiert auch schon, aber eben im Hauptteil meines Programms, oder ich mach da was falsch.

Hier mal der restliche Code:

Code: Alles auswählen

/*
Resmaker.h
*/

#include <QWidget>
#include <QtXml>
#include "ui_resmaker.h"
#include "myparser.h"

class QXmlSimpleReader;
class QXmlInputSource;

class Resmaker : public QWidget, public Ui_Resmaker
{
	Q_OBJECT

public:
	Resmaker();
public slots:
	void stepOne();
	void stepTwo();
	void resVis();
private:
	QXmlSimpleReader reader;
};

Code: Alles auswählen

/*
Resmaker.cpp
*/

#include <QtGui>
#include <iostream>
#include "resmaker.h"

Resmaker::Resmaker()
	: Ui_Resmaker()
{
	setupUi(this);

	secondGroupBox->setEnabled(false);
	okButton->setEnabled(false);
	resGroupBox->setEnabled(false);

	connect(cancelButton, SIGNAL(clicked()), qApp, SLOT(quit()));
	connect(processComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(stepOne()));
	connect(deviceComboBox, SIGNAL(activated(int)), this, SLOT(stepTwo()));
	connect(okButton, SIGNAL(clicked()), this, SLOT(resVis()));
}

void Resmaker::stepOne()
{
	secondGroupBox->setEnabled(true);
	int number = deviceComboBox->count();
	deviceComboBox->addItem("None");
	while (number > 0){
		deviceComboBox->removeItem(number);
		number--;
	}
	if (processComboBox->currentText() == "IPCSMSServer"){
		deviceComboBox->addItem("Motor");
		deviceComboBox->addItem("AnalogInput");
	}
	else if (processComboBox->currentText() == "RS485"){
		deviceComboBox->addItem("test");
		deviceComboBox->addItem("test3");
	}

}

void Resmaker::stepTwo()
{
	okButton->setEnabled(true);
}

void Resmaker::resVis()
{
	resGroupBox->setEnabled(true);
	MyParser handler;
	QFile file("IPCSMSServer.xml");
	QXmlInputSource source(&file);
	reader.setContentHandler(&handler);

	bool ok = reader.parse(source);
	if (!ok){
		std::cout << "error" << std::endl;
	}
	else{
		std::cout << "ok" << std::endl;
	}

}
Und zu guter letzt die Main

Code: Alles auswählen

/*
main.cpp
*/

#include <QApplication>
#include "resmaker.h"

int main( int argc, char** argv )
{
	QApplication app( argc, argv );

	Resmaker *res = new Resmaker();
 	res->show();

	return app.exec();
}
Evtl. wirds dadurch etwas klarer.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

setupUi() ist eine (DIE entscheidende) Methode deines Ui_Resmaker. Wenn du das nicht in MyParser im Konstruktor aufrufst, sind deine Member (wie z.B. der fatale resEdit) nicht initialisisert (NULL-Pointer), wodurch es bei einem Zugriff zu einer Zugriffsverletzung kommt.

Prinzipiell solltest du deinen Ansatz nochmal überdenken. Was braucht dein MyParser überhaupt ne Ui? setupUi wird übrigens fehlschlagen, da das als Argument ein QWidget braucht, und MyParser nicht davon erbt.
Deine Klassen sind etwas - verworren ;)
HappyEnding
Beiträge: 26
Registriert: 5. März 2009 14:15

Beitrag von HappyEnding »

Hmmm, ok danke schonmal soweit. Eigentlich wollte ich das qName auch lieber per return zurueckgeben, aber da es bool is und ich keine andere Methode gefunden hab, hab ichs mal so probiert. Und wie sonst soll der Parser auf Teile der UI zugreifen wenn nicht so, aber gut versteh deine Bedenken.
Evtl. nen Tipp fuer ne Alternative?
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

@franzf: "nicht initialisisert" != "NULL-Pointer" .....

@HappyEnding: sei dir den "Rollen" (also den Aufgaben) deiner Klassen immer bewusst... eine Klasse kann eine GUI (oder ein Teil davon) sein und graphischer Elemente verwalten... ein Parser hat jedoch andere Aufgaben und sollte eine entsprechende Schnittstelle haben. Also entweder die GUI laesst den Parser seine Arbeit tun und fragt hinterher die Ergebnisse ab (in diesem Fall kannst du ja eigene Methoden implementieren (wie z.B. "QString qName() const")) oder du laesst dir die Ergebnisse zusenden (eigene SIGNALs in MyParser und SLOTs in GUI).
HappyEnding
Beiträge: 26
Registriert: 5. März 2009 14:15

Beitrag von HappyEnding »

Ok danke, werd ich ab jetzt mal genauer einhalten. Und vor allem danke fuer die schnelle hilfe hier, sitz hier schon ne ganze weile und bin ned weitergekommen.

mfg
HappyEnding
Antworten