Seite 1 von 1
[erledigt] Segmentation Fault bei QTextEdit::plainText
Verfasst: 25. März 2009 21:01
von Godless
Hallo,
ich beschäftige mich noch nicht allzulang mit Qt und schreibe gerade zu Übungszwecken einen kleinen Texteditor. Ich habe mir eine eigene Klasse namens TextEdit von QTextEdit abgeleitet, um z.B. eine
open-Methode direkt im Textfeld zu implementieren, was soweit auch funktioniert.
Das Problem liegt beim Speichern: Jedes Mal wenn ich - egal ob zum Setzen per
setPlainText() oder zum Auslesen per
toPlainText() - auf den plainText zugreife.
Die save-Methode, bei der es hapert, ist recht kurz und sieht folgendermaßen aus:
Code: Alles auswählen
void TextEdit::save(const QString& filePath)
{
QFile file(filePath);
QString editContent = QTextEdit::toPlainText();
// an dieser Stelle bricht die Ausführung des Programmes ab
// und er sendet mir ein "Segmentation Fault"
file.write(editContent.toAscii());
}
gdb sagt mir, das Segmentation-Fault-Signal werde von der Methode QTextDocument::isUndoRedoEnabled() gesendet, was mir aber nicht groß weiterhilft, da ich diese Funktion nirgendes aufrufe. Die exakte Fehlermeldung sieht folgendermaßen aus:
Code: Alles auswählen
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7f1a9aded6f0 (LWP 6730)]
0x00007f1a9a46ceb4 in QTextDocument::isUndoRedoEnabled ()
from /usr/lib/libQtGui.so.4
Hilft das jemandem weiter?
Ich wäre sehr dankbar, wenn mir jemand weiterhelfen könnte. Ich bastle schon seit zwei Tagen an dem Problem, aber es will sich einfach nicht lösen lassen.
MfG Godless
Verfasst: 25. März 2009 21:26
von FaS
toPlainText() ist keine statische Funktion -> lass "QTextEdit::" weg.
Dann wirst du bei der nächsten Zeile den nächsten Fehler erhalten: Bevor in eine Datei geschrieben werden kann, muss sie geöffnet werden. Sie dir die Qt-Dokumentation an.
Gruß,
FaS
Verfasst: 26. März 2009 08:12
von pfid
FaS hat geschrieben:toPlainText() ist keine statische Funktion -> lass "QTextEdit::" weg.
Dann wirst du bei der nächsten Zeile den nächsten Fehler erhalten: Bevor in eine Datei geschrieben werden kann, muss sie geöffnet werden. Sie dir die Qt-Dokumentation an.
Gruß,
FaS
Das QTextEdit:: hat in seinem Fall nichts mit statisch zu tun; er ruft hier explizit die Methode der QTextEdit Klasse auf. Würde QTextEdit:: fehlen, würde die Methode (seiner abgeleiteten) TextEdit Klasse aufgerufen.
QTextEdit:: kann jedoch trotzdem weggelassen werden, falls die entsprechende Methode in der Child-Klasse nicht neu oder nicht-virtuell implementiert ist
Verfasst: 26. März 2009 09:18
von solarix
abgesehen von den erwähnten Punkten denke ich, dass der Fehler woanderst liegt (vor dem Aufruf von "TextEdit::save()"). Ist die Instanz von "TextEdit" überhaupt gültig? Wo/Wie wird sie erzeugt/verwaltet?
Verfasst: 26. März 2009 18:19
von Godless
Upps, da entschuldige ich mich mal, dass ich die Dokumentation nicht sorgfältig gelesen habe

Das .open() hat leider auch nichts genützt, der Fehler bleibt derselbe.
Die Methode ist zwar nicht redefiniert, ich rufe aber trotzdem Methoden von QTextEdit in meiner Klasse so auf. (Einfach eine Angewohnheit, ohne geht's genau so wenig)
Gültig sollte das ganze schon sein, vor allem, da Öffnen und dergleichen problemlos funktioniert. Die Instanz wird in der
open-Methode einer von QTabWidget abgeleiteten Klasse erzeugt (dynamisch natürlich), die wie folgt aussieht:
Code: Alles auswählen
void TabWidget::openFile(const QString& path)
{
TextEdit* edit = new TextEdit(QString(""));
QString tabTitle = edit->openFile(path);
int index = QTabWidget::addTab(edit,tabTitle);
QTabWidget::setCurrentIndex(index);
}
Diese Methode wiederum wird in einem Slot meines Hauptfensters aufgerufen.

ch weiß, ist ein wenig umständlich, aber ich bin eben so.)
Öffnen etc. funktioniert problemlos. Ich habe es mittlerweile sogar hinbekommen, dass in der open-Methode von TextEdit setPlainText funktioniert. Nur beim Speichern will er wieder nicht.
//Edit: Seltsamerweise funktioniert dieselbe Methode, auf dieselbe Art aufgerufen, in der open-Methode meiner TextEdit-Klasse problemlos!
Verfasst: 26. März 2009 18:25
von Christian81
Ohne Testcase kommen wir wohl nicht wirklich weiter
Verfasst: 26. März 2009 20:19
von solarix
den Aufruf von "save(..)" sehen wir noch immer nicht...
Verfasst: 27. März 2009 19:34
von Godless
Das ist seltsam... auf einmal funktioniert es. Ich kann leider nicht genau sagen, was der Fehler war, da ich sehr viel herumprobiert und nur wenig von dem, was ich umgeändert beibehalten habe. Letztendlich hat es funktioniert, nachdem ich festgestellt habe, dass ich versehentlich die nichtexistente Methode
saveFile der Klasse TabWidget aufgerufen habe, statt die des
currentWidget(). Warum der Compiler das anstandslos kompiliert hat, ist mir fraglich und obwohl er es getan hat, kann ich mir nicht vorstellen, dass das zu einer Segmentation fault führen würde.
Egal, ich bin froh, dass es jetzt mit folgendem Code in der
save()-Methode funktioniert:
Code: Alles auswählen
void TextEdit::saveFile(const QString& fileName)
{
QFile file(fileName);
if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
return;
}
QString cont = QTextEdit::toPlainText();
QByteArray content = cont.toAscii();
file.write(content);
}
Danke an alle, die versucht haben, mir zu helfen!
MfG Godless
//Edit: Oh mein Gott bin ich blöd! Mir fällt gerade auf wie offensichtlich der Fehler war, den ich gemacht habe: Ich habe - da currentWidget() ja ein QWidget zurückliefert - das ganze zu meiner abgeleiteten TextEdit-Klasse gecastet, die ja ebenfalls indirekt von QWidget erbt. Da ich das currentWidget() vergessen habe, hat er das normale TabWidget genommen und - da es ja ebenfalls von QWidget abgeleitet ist - dieses in ein TextEdit umgewandelt, das natürlich keine save()-Methode hat...
Verfasst: 28. März 2009 11:32
von solarix
soviel zum Thema
Gültig sollte das ganze schon sein
Kleiner Hinweis: genau aus diesem Grund verwendet man für solche Casts "qobject_cast" oder "dynamic_cast":
Code: Alles auswählen
TextEdit *txt = dynamic_cast<TextEdit*>(aWidget);
Q_ASSERT(txt);
Dann hättest du keine zwei Tage gebraucht, sondern nur zwei Sekunden

Verfasst: 20. April 2009 13:07
von franzf
Godless hat geschrieben:Die Methode ist zwar nicht redefiniert, ich rufe aber trotzdem Methoden von QTextEdit in meiner Klasse so auf.
Sry, ist schon etwas her, wollte da aber nochmal nachhaken.
BITTE BITTE gewohn dir das ab

Auch wenn es bisher geklappt hat, kannst du da in eine ganz doofe Falle tappen.
Folgendes Beispiel:
Code: Alles auswählen
#include <iostream>
using namespace std;
class A
{
public:
void foo()
{
bar();
}
virtual void bar()
{
cout << "A::bar()" << endl;
}
};
class B : public A
{
public:
void bar()
{
cout << "B::bar()" << endl;
}
void test()
{
A::bar();
}
};
class C : public B
{
public:
void bar()
{
cout << "C::bar()" << endl;
}
};
int main()
{
C c;
c.bar();
c.foo();
c.test();
return 0;
}
Setze A==QTextEdit, B==deine TextEdit-Klasse.
Dann kommt jemand daher und leitet von deiner TextEdit-klasse ab.
Oder vllt. implementierst du am Ende selber eine der virtuellen Funktionen neu.
Wenn die in irgend einer deiner bereits existierenden Methoden aufgerufen werden soll, und da steht dann immer "QTextEdit::someVirtualFunc()", hast du ein Problem da NIEMALS deine aufegrufen werden kann!!!
Mein Beispiel arbeitet jetzt immer mit cout, aber stell dir vor da passiert mehr hinter den Kulissen, beispielsweise in irgend welchen Models! Plötzlich klappt gar nix mehr!
Wenn du in meinem Beispiel in B::test() den Aufruf "A::bar()" durch "bar()" ersetzt, passt wieder alles, und auch die letzte der 3 Ausgaben liefert "C::bar()", wie man sich das so auch erwarten würde.
Grüße
Franz