Seite 1 von 2

[gelöst] Anwendung startet nur sporadisch

Verfasst: 20. August 2009 18:35
von 101
Hallo Zusammen,

ich habe ein größeres Problem mit meiner Anwendung unter Windows.

Nach dem Instanziierung der Applikation:

Code: Alles auswählen

QApplication app(argc, argv);
wird ein mainWindow instanziiert indem wird ein Widget als MainWindow instanziiert (dieses ist mit dem Designer als UI Datei erstellt).
Dann wird die Applikation gestartet:

Code: Alles auswählen

app.exec();
Das Kompilieren verläuft ohne Fehler. Die EXE kann ich aber nur sporadisch starten. Wenn die Anwendung nicht startet kommt die Fehlermeldung "Die Anweisung in 0x... verweis auf Speicher "0x0..". Mit dem Debugger komme ich bis zum Codeabschnitt im Konstruktor des Widgets:

Code: Alles auswählen

ui.setupUi(this);
Der Debugger wirft folgende Meldung!

Must construct a QApplication before a QPaintDevice

Kann es sein, das der Start meiner Application sporadisch durch Windows verhindert wird?

Ich komme hier mit der Fehlersuche hier nicht weiter, weil ich keinen Fehler sehe. Wenn die Anwendung erst einmal ohne Fehlermeldung gestartet ist läuft auch Alles!

Verfasst: 20. August 2009 18:37
von solarix
Wie upsala so gerne schreibt: wenn der Code geheim ist, ist auch die Lösung geheim...

Verfasst: 20. August 2009 19:01
von 101
Geheim ist hier nichts :)! Ich will hier nur nicht alles zumüllen, weil der Code auf mehrere Files verteilt ist!

Mir geht es hauptsächlich um das Verständnis. Wie kann eine Anwendung mal ohne Fehler starten und dann mal wieder nicht?

Verfasst: 20. August 2009 19:30
von Christian81
Ich tippe auf eine statische Variable die auf die PaintDevice zugreift - QImage oder so. Diese wird natürlich vor main() initialisiert und fertig ist das Problem.
So lange Code aus der Anwendung rausnehmen bis es korrekt funktioniert würde ich sagen

Verfasst: 20. August 2009 19:41
von 101
Könnte es auch die Einbindung des Ui-Files im Header der Widget Klasse sein?

Code: Alles auswählen

class clSubWidget_1: public QWidget
 {
     Q_OBJECT

 public:
      clSubWidget_1(QWidget *parent = 0);

 ...

 private:
     Ui::sub_1 ui;  
  };
Im UI-File wird ja QPaintDevice verwendet.

Verfasst: 20. August 2009 19:44
von Christian81
Wenn Du die Klasse erst nach QApplication instanziierst was Du ja behauptest - nein.

Verfasst: 20. August 2009 19:53
von 101

Code: Alles auswählen

QApplication app(argc, argv);
ist die erste Zeile im main().

:?

Verfasst: 20. August 2009 20:07
von solarix
Wie kann eine Anwendung mal ohne Fehler starten und dann mal wieder nicht?
Meistens weil mit Pointern was durcheinander gebracht wurde... was sich dann halt je nach Speicherinhalt anderst verhält. Daher: Code her.. wengistens die wichtigsten Abschnitte wie z.B. Konstruktoren..
ist die erste Zeile im main().
Das Spielt keine Rolle.... Statische Variabeln werden vor main() erzeugt.. und da wir kein Code haben, wird halt geraten..

Verfasst: 20. August 2009 21:59
von 101
Hier die "Konstruktor Kette", irgend etwas läuft hier falsch:

Code: Alles auswählen

#include "main.h"


int main(int argc, char *argv[])
{
	QApplication app(argc, argv);
	QApplication::setStyle("windowsxp");
	//XML Config einlesen
	mapConfig = new QMap<QString,QString>;
	QFile file(app.applicationDirPath () + "/config.xml");
	QXmlInputSource inputSource(&file);
	QXmlSimpleReader xmlReader;
	xmlHandler = new clXML_PARSE(mapConfig);
	xmlReader.setContentHandler(xmlHandler);
	xmlReader.setErrorHandler(xmlHandler);
	xmlReader.parse(inputSource);
	MainWindow = new clVISUAL(0,Qt::WindowStaysOnTopHint, mapConfig);	
	//Main Window in Bildschirmmitte zentrieren
   Desktop = QApplication::desktop();
	MainWindow->move((Desktop->width()-MainWindow->width())/2,(Desktop->height()-MainWindow->height())/2);
	MainWindow->show();
	return app.exec();
}
Konstruktor MainWindow:

Code: Alles auswählen

clVISUAL::clVISUAL(QMainWindow *parent,Qt::WindowFlags flags,QMap<QString,QString>* map):QMainWindow(parent,flags)
{
	mapConfig = map;
	ui.setupUi(this);
	SiteStack = new QStackedWidget(this);
	//StackWidget Initialisieren
	SiteController = new clSITE_CONTROL(SiteStack, &ui);
}
Konstruktor SiteControl:

Code: Alles auswählen

clSITE_CONTROL::clSITE_CONTROL(QStackedWidget* SiteStackMain, Ui::VISUALClass *uiMainWindow)
{
	//ui Pointer auf MainWindow
	ui = uiMainWindow;
	//Seiten Initialisieren
	Site_Init = new clSITE_INIT(this,mConfig,0);
    SiteStack->addWidget(Site_Init);
	Site_Start = new clSITE_START(this,mConfig,100);
    SiteStack->addWidget(Site_Start); 
}
Hier als Beispiel der Konstruktor von clSITE_START:

Code: Alles auswählen

clSITE_START::clSITE_START(QWidget* parent, MAIN_Config_t* config, quint16 cycletime) : QWidget(parent)
{
	ui.setupUi(this);
	m_Config = config;
	m_CycleTime = cycletime;
	//Update Timer initialisieren
	m_Timer = new QTimer();
	connect(m_Timer, SIGNAL(timeout()), this, SLOT(UpdateView()));
}

Verfasst: 20. August 2009 22:04
von Christian81
Ist es so schwer so lange alles auszukommentieren bis man weiss wo es genau crasht? Dort wo Du meinst ist es definitv nicht der Fall...
Es würde sich auch lohnen einen Breakpoint auf den assert in QPaintdevice zu setzen - dazu braucht man aber ein Qt mit debug-Symbolen.

Verfasst: 20. August 2009 22:33
von NoRulez
Ich persönlich würde Pointer udgl. in der Initialisierungsliste initialisieren.
Also Beispielsweise statt:

Code: Alles auswählen

clSITE_CONTROL::clSITE_CONTROL(QStackedWidget* SiteStackMain, Ui::VISUALClass *uiMainWindow)
{
   //ui Pointer auf MainWindow
   ui = uiMainWindow; 
.
.
.
einfach

Code: Alles auswählen

clSITE_CONTROL::clSITE_CONTROL(QStackedWidget* SiteStackMain, Ui::VISUALClass *uiMainWindow) : ui(uiMainWindow)
{
.
.
.
und falls ein Pointer nicht am Anfang initialisiert wird dann halt

Code: Alles auswählen

clSITE_CONTROL::clSITE_CONTROL(QStackedWidget* SiteStackMain, Ui::VISUALClass *uiMainWindow) : ui(0)
und das dann generell für alle Membervariablen, somit ersparst Du Dir genauso die Suche bei solchen Fehlern, gerade was Pointer angeht.

Desweiteren...ich will zwar jetzt nicht kritisieren, aber verwendest Du einen Coding-Standard? Ich persönlich finde so Klassennamen wie "clSITE_CONTROL" sehr unleserlich. Würde Dir eher empfehlen Sie beispielsweise "ClSiteControl" zu nennen, dann würde sich der Code etwas leichter lesen lassen.

Wie schon die meisten hier geschrieben haben würde auch ich gerne ein bisschen mehr Code sehen um helfen zu können.

Falls es nicht SO geheim ist, dann füge doch die Dateien bei denen Du glaubst das sie fehlerhaft sind als Attachement hinzu.

LG NoRulez

Verfasst: 20. August 2009 23:10
von 101
Assert auf QPaintDevice? Habe ich noch nie gemacht. Ich verwende Qt4.5 Free Version und als GUI QtDevelop. Im Debuger bleibe ich bei

Code: Alles auswählen

Site_Start = new clSITE_START(this,mConfig,100); 
und da bei

Code: Alles auswählen

ui.setupUi(this);
hängen. In der UI werden in einem Designer Plugin auch Bilder aus der Ressource angezeigt. Aber das kann ja nicht das Problem sein?
So für heute ist erst mal Schluss, habe die Nase voll :)

Ach ja, auskommentieren ist schlecht, da der Fehler z.B. erst beim 10. Start auftritt.

Verfasst: 20. August 2009 23:20
von NoRulez
Du könntest die Plugins mal weglassen.
Hast Du schon mal probiert kleine UnitTests für die entsprechende Module zu schreiben und vielleicht so den Fehler zu finden?

LG NoRulez

Verfasst: 21. August 2009 09:27
von solarix
hmmm.. zwei Fragen:

1. Du scheinst globale Variabeln zu haben.. wie sieht die main.h aus?
2. in clSITE_CONTROL scheinst du eine Variabel "mConfig" des Typs "MAIN_Config_t*" zu haben.. .wo wird diese Initialisiert?

Verfasst: 21. August 2009 09:28
von 101
Ich habe jetzt mein Programm auf das minimalste gekürzt, um den Fehler einzukreisen!

Hier die main.h:

Code: Alles auswählen

#ifndef __MAIN_H__
#define __MAIN_H__

#include "mainwindow.h"

#include <QtGui>
#include <QApplication>

QDesktopWidget *Desktop;
clVISUAL *MainWindow;

#endif // __MAIN_H__

hier die main.cpp:

Code: Alles auswählen

#include "main.h"

int main(int argc, char *argv[])
{
	
	QApplication app(argc, argv);
	QApplication::setStyle("windowsxp");
	//Main Window generieren und Anzeigen
	Desktop = QApplication::desktop();
	MainWindow = new clVISUAL(0,Qt::WindowStaysOnTopHint);	
	//Main Window in Bildschirmmitte zentrieren
	MainWindow->move((Desktop->width()-MainWindow->width())/2,(Desktop->height()-MainWindow->height())/2);	
	MainWindow->show();
	return app.exec();
}
hier die MainWindow.h:

Code: Alles auswählen

#ifndef __MAINWINDOW_H
#define __MAINWINDOW_H

#include <QtGui/QWidget>
#include <QMainWindow>
#include <QLayout>
#include <QDebug>
#include <QStackedWidget>


#include "ui_visual.h"
#include "site_start.h"

class clVISUAL : public QMainWindow
{
    Q_OBJECT

public:
    clVISUAL(QMainWindow *parent = 0,
    		  Qt::WindowFlags flags = 0);
	
	clSITE_START *Site_Start;
	QGridLayout *MainLayout;
	QStackedWidget *SiteStack;

private:
    Ui::VISUALClass ui;

};

#endif // MAINWINDOW_H

hier die MainWindow.cpp:

Code: Alles auswählen

#include "rs_visual.h"

//MainWindow Konstruktor
clVISUAL::clVISUAL(QMainWindow *parent,Qt::WindowFlags flags):QMainWindow(parent,flags)
{
	ui.setupUi(this);
	//Klassen instanziieren
	SiteStack = new QStackedWidget();
	//MainLayout definieren
	Site_Start = new clSITE_START;
	SiteStack->addWidget(Site_Start);
	MainLayout = new QGridLayout();
	MainLayout->setSpacing(0);
	MainLayout->setMargin(0);
	MainLayout->addWidget(SiteStack);
	ui.frame_2->setLayout(MainLayout);
}
Hier die Startseite.h:

Code: Alles auswählen

#ifndef __SITE_START_H__
#define __SITE_START_H__

//
#include <QtGui>
//
#include "ui_site_start.h"
//
class clSITE_START : public QWidget
{
	Q_OBJECT

public:
	clSITE_START(QWidget* parent=0);

private:
	Ui::site_start ui;   

};
#endif // __SITE_START_H__
Hier die Startseite.cpp:

Code: Alles auswählen

#include "site_start.h"

//Konstruktor
clSITE_START::clSITE_START(QWidget* parent) : QWidget(parent)
{
	QString strTitle = "Hauptseite";
	qDebug() << "I> Konstruktor Seite " << strTitle;
	ui.setupUi(this);
}
Das ist Alles! Sobald ich mehrere Widgets per Designer in der UI enbinde, startet die Anwendung nicht mehr!