SIGSEGV nur unter Linux bei Datenübernahme aus einem Wizard

Alles rund um die Programmierung mit Qt
Antworten
barahir1983
Beiträge: 21
Registriert: 30. August 2010 14:51
Wohnort: Jena
Kontaktdaten:

SIGSEGV nur unter Linux bei Datenübernahme aus einem Wizard

Beitrag von barahir1983 »

Hallo Community,

ich habe ein relativ seltsames (und vielleicht auch betriebssystemspezifisches) Problem bei der Übernahme von Daten aus einem Wizard.
Ich definiere und fülle in diesem Wizard die Variable "header" folgendermaßen:

Code: Alles auswählen

public:
    explicit NAHeaderWizard(QWidget *parent = 0);
    ~NAHeaderWizard();
    QStringList header;
...

void NAHeaderWizard::accept()
{
    header.append("name:"+ui->nameE->text()+";");
    if (!ui->commentaryE->text().isEmpty())
        header.append("commentary:"+ui->commentaryE->text()+";");
    if (!ui->annotation1E->text().isEmpty())
        header.append("annotation:"+ui->annotation1E->text()+";");
    if (!ui->annotation2E->text().isEmpty())
        header.append("annotation:"+ui->annotation2E->text()+";");
     
   ... (hier folgen noch weitere Aufnahmen in die StringList)
    QDialog::accept();
}
Im Hauptprogramm wird der Inhalt der QStringList dann so eingefügt:

Code: Alles auswählen

void NaProg::on_actionHeader_Wizard_triggered()
{
    NAHeaderWizard wiz;
    if (activeMdiChild())
    {
        if (wiz.exec() == QDialog::Accepted)
        {
            QStringList::const_iterator it;
            for (it= wiz.header.constBegin(); it!= wiz.header.constEnd();++it)
            {
            activeMdiChild()->append(*it);
            }
        }
    }
    else
    {
        neu();
        if (wiz.exec() == QDialog::Accepted)
        {
            QStringList::const_iterator it;
            for (it= wiz.header.constBegin(); it!= wiz.header.constEnd();++it)
            {
            activeMdiChild()->append(*it);
            }
            activeMdiChild()->append("");
            on_actionClef_triggered();
        }
    }
}
Unter Windows und MacOS X funktioniert das alles auch und zum Schluss ist dann der Header in dem MDI-Fenster. Unter Linux passiert abwechselnd nichts, oder es gibt einen Segmentation fault. Ich habe leider keine Ahnung, was genau da schiefläuft und habe offen gestanden auch zu wenig Ahnung von den Unterschieden der Fensterverwaltung in den einzelnen Betriebssystemen, die möglicherweise dafür verantwortlich sind. Möglicherweise habe ich auch einfach nur Glück unter Windows und Mac OS X und das geht gar nicht so... :)

Wer hat Ideen zu diesem Problem? Über jedes "Augenöffnen" bin ich sehr dankbar, da auch Linux zu meinen Zielsystemen gehört und das natürlich blöd ist, dass es hier noch nicht funktioniert.

Liebe Grüße
barahir1983
Zuletzt geändert von barahir1983 am 28. November 2010 19:17, insgesamt 1-mal geändert.
QtCreator 2.5 beta und Qt Libraries 4.8.0 auf MacOS X 10.7.3
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

SIGSEGV ist immer böse und hat in fast 100% der Fälle mit fehlerhaftem Code auf deiner Seite zu tun. Auch wenn es nur auf einer Plattform zu Tage tritt.
Kannst du mal ein kompilierbares Minimalbeispiel posten, das den Laufzeitfehler aufweist? Ableitungen etc beibehlaten wie im Original. Mich würde auch noch interessieren, wie du in das "accept" gelangst.
barahir1983
Beiträge: 21
Registriert: 30. August 2010 14:51
Wohnort: Jena
Kontaktdaten:

Beitrag von barahir1983 »

Hallo!

Leider bin ich gerade erst nach Hause gekommen und muss morgen recht früh raus, werde mich aber bald ans Minimalbeispiel setzen. Nur zu accept() ein Wort: Soweit ich weiß, wird das automatisch ausgelöst, sobald ich im Wizard auf "Fertigstellen" gehe. Also nicht über expliziten Aufruf meinerseits.

Mein Verdachtsmoment fällt immer wieder auf das activeMdiChild() der MdiArea. Ich hoffe, morgen ein Nichtfunktions-Beispiel geben zu können (mit einem einfachen Programm mit Textedit hat es nämlich funktioniert, auch unter Linux... (dieses Beispiel häng ich erstmal an, für die Funktionsweise an sich)

Liebe Grüße

barahir1983
Dateianhänge
minimalbeispiel-wizard-connection.7z
(3 KiB) 183-mal heruntergeladen
QtCreator 2.5 beta und Qt Libraries 4.8.0 auf MacOS X 10.7.3
barahir1983
Beiträge: 21
Registriert: 30. August 2010 14:51
Wohnort: Jena
Kontaktdaten:

Beitrag von barahir1983 »

So, nun hier das versprochene Minimalbeispiel auf Basis des MDI-Beispiels von Qt...

Es führt genau zum "gewünschten" Fehlverhalten, nämlich einem schnöden "Segmentation fault" bei Ausführung von Test wizard. Um das Verhalten zu reproduzieren, muss man zunächst eine neue Datei erstellen, dann File->Test wizard ausführen; nach Click auf "Fertig" / "Done" wird der Segfault ausgelöst.

Tut mir leid wegen der längeren Verzögerung, dieses Wochenende hat mich mit mehr Arbeit als gedacht in Beschlag genommen...

Vielen Dank für alle Ideen/Vorschläge im Voraus
barahir1983
Dateianhänge
testwiz-crashbeispiel.7z
(43.98 KiB) 165-mal heruntergeladen
QtCreator 2.5 beta und Qt Libraries 4.8.0 auf MacOS X 10.7.3
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Code: Alles auswählen

void MainWindow::testwizard()
{
    Wizard wiz;
    MdiChild *active = activeMdiChild();
    if(!active) return;
    if (wiz.exec() == QDialog::Accepted)
    {
        QStringList::const_iterator it;
        for (it= wiz.header.constBegin(); it!= wiz.header.constEnd();++it)
        {
        active->append(*it);
        }
    }
}
Dein Fenster hat direkt nach dem exec() noch keinen Focus, deshalb gibt es kein aktives MdiArea. Vor dem exec() zu prüfen macht also keinen Sinn.
Abänderung wie oben und es geht.

Der große Fehler bei deinem Code liegt in der ungeprüften Annahme, dass du nie und nirgends NULL-Pointer bekommst. Wenn du die Prüfung if(activeMdiChild()) in den exec()-if-Block ziehst, gibt es keinen SegFault - es wird nur auch kein Text eingefügt :P

Du castest auch recht gerne, ohne den return zu prüfen. Auch qobject_cast liefert bei nicht möglichem cast einen NULL-Pointer zurück. Den zu dereferenzieren löst einen SegFault aus. Geh mal deinen Code nach "_cast" durchsuchen und staune, wie viele potentielle Fehlerquellen du finden wirst :P
barahir1983
Beiträge: 21
Registriert: 30. August 2010 14:51
Wohnort: Jena
Kontaktdaten:

Beitrag von barahir1983 »

Hallo und vielen Dank für die Antwort :)

Ich muss gestehen, die Stellen an denen qobject_cast so munter verwendet werden, habe ich noch aus dem QT-Beispiel, da hatte ich momentan noch nicht selbst dran gearbeitet... wie umgeht man denn die Gefahr "richtig"?
Wäre der Ansatz, statt jedes "if (activeMdiChild())" deinen Vorschlag

Code: Alles auswählen

MdiChild *active = activeMdiChild(); 
    if(!active) return; 
brauchbar oder sollte ich besser alles was mit der Überprüfung von MDI-Childs zusammenhängt noch mal neu schreiben?
Bitte um Entschuldigung, wenn meine Fragen etwas "doof" sind, ich bin erst seit einem halben Jahr aktiv an der Qt-Programmierung...

Habe gerade den Vorschlag eingearbeitet und siehe da, unter Linux klappts jetzt auch mit dem Einfügen :)

Liebe Grüße und vielen Dank
barahir1983
QtCreator 2.5 beta und Qt Libraries 4.8.0 auf MacOS X 10.7.3
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

barahir1983 hat geschrieben:Ich muss gestehen, die Stellen an denen qobject_cast so munter verwendet werden, habe ich noch aus dem QT-Beispiel, da hatte ich momentan noch nicht selbst dran gearbeitet... wie umgeht man denn die Gefahr "richtig"?
Indem man den return prüft.

Code: Alles auswählen

QWidget* w = new QTextEdit;
QTextEdit* t = qobject_cast<QTextEdit*>(w);
Q_ASSERT(t) // der geht gut
QLineEdit* e = qobject_cast<QLineEdit*>(w);
Q_ASSERT(e) // der geht schief - ein QTextEdit ist einfach kein QLineEdit, deshalb gibt der cast NULL zurück 
Q_ASSERT ist natürlich nur dann i.O., wenn es sich um nen Programmierfehler handelt. Ein normales "if(e)" tut es in den meisten Fällen.
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

Auf die Lösung mit dem Nullpointer wärst du übrigens auch gekommen, wennn du dir einfach mal den Backtrace des Core-Files angeschaut hättest ;) (sofern ulimit das erzeugen erlaubt..)
barahir1983
Beiträge: 21
Registriert: 30. August 2010 14:51
Wohnort: Jena
Kontaktdaten:

Beitrag von barahir1983 »

Ich werd mal sehen, dass ich das wasserfest abdichte :)

@pfid: Ich glaube nur bedingt, dass ich da drauf gekommen wäre, ich habe leider immer noch das Gefühl, bei Qt zu schwimmen, früher mit Delphi wars alles so "einfach" bzw. ich hab an sowas nie gedacht... Aber es ist gut zu wissen, so kümmere ich mich in Zukunft auch um die Null-pointer.

Liebe Grüße
barahir1983
QtCreator 2.5 beta und Qt Libraries 4.8.0 auf MacOS X 10.7.3
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

barahir1983 hat geschrieben:Ich werd mal sehen, dass ich das wasserfest abdichte :)

@pfid: Ich glaube nur bedingt, dass ich da drauf gekommen wäre, ich habe leider immer noch das Gefühl, bei Qt zu schwimmen, früher mit Delphi wars alles so "einfach" bzw. ich hab an sowas nie gedacht... Aber es ist gut zu wissen, so kümmere ich mich in Zukunft auch um die Null-pointer.

Liebe Grüße
barahir1983

Code: Alles auswählen

09:12:54 ~> gdb [binary] [core-file]

GNU gdb (GDB) 7.1-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) bt [enter]
Dann suchst du nach der Zeile in der this=0x0 steht, und fixt den Bug ;)
barahir1983
Beiträge: 21
Registriert: 30. August 2010 14:51
Wohnort: Jena
Kontaktdaten:

Beitrag von barahir1983 »

Danke, wieder was neues gelernt :)
QtCreator 2.5 beta und Qt Libraries 4.8.0 auf MacOS X 10.7.3
Antworten