Programm beenden

Alles rund um die Programmierung mit Qt
C167
Beiträge: 105
Registriert: 9. Februar 2008 20:30

Programm beenden

Beitrag von C167 »

Mein Programm soll sich selbst beenden sobald ein Fehler auftritt. Mein Konstruktor:

Code: Alles auswählen

initDatabase();
createUi();
createActions();
createMenus();
createDocks();
init();
In der Funktion initDatabase() wird eine Datenbankverbindung aufgebaut. Schlaegt das fehl, soll beendet werden. Dazu sieht das Teil so aus:

Code: Alles auswählen

void cdlauncher::initDatabase()
{
	db = QSqlDatabase::addDatabase ( "QSQLITE" );
	db.setDatabaseName ( QDir::currentPath() +"/../db.dat" );
	if (db.open() )
	{
		QMessageBox::critical ( this, tr ( "Error" ), tr ( "Die zentrale Datenbank konnte nicht gefunden werden.\nUnter Umständen handelt es sich dabei um einen Programmierfehler,\nbitte senden Sie eine E-Mail an den Author." ), QMessageBox::Ok, QMessageBox::NoButton );
		QCoreApplication::exit(0);
	}
}
Ich provoziere testweise einen Fehler indem ich die Datenbank verschiebe. Die Message-Box geht auch auf, nur wird dannach das Programm nciht beendet, sondern rennt weiter, und die nachfolgenden Klassen, die auf die Datenbank zugreifen, geben eine Menge Fehler von sich, bis das Programm einen SegFault bekommt und terminiert wird. Der eventLoop wurde in der main-Methode per

Code: Alles auswählen

return app.exec();
gestartet, also sollte die Sache sich beenden. Warum tut das nicht wie es tun soll?
C167
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Doku lesen -> http://doc.trolltech.com/4.3/qcoreapplication.html#exit
After this function has been called, the application leaves the main event loop and returns from the call to exec(). The exec() function returns returnCode. If the event loop is not running, this function does nothing.
Da steht nichts von 'exits immediatelly' ...
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Der Neue
Beiträge: 24
Registriert: 31. Mai 2006 14:45

Beitrag von Der Neue »

Hallo
Das müsste eigentlich schon funktionieren, ist zumindest bei mir der Fall.

Der Konstruktor wird sicher erst nach app.exec() ausgeführt? Nicht, dass du das Objekt schon vorher erstellst, dann hat das natürlich keine Wirkung.

mfg

Sorry, hat sich dann wohl erledigt.
Gesegnet sein all die, die nichts zu sagen haben
und trotzdem den Mund halten.
C167
Beiträge: 105
Registriert: 9. Februar 2008 20:30

Beitrag von C167 »

Da steht nichts von 'exits immediatelly' ...
Ich war eigentlich der Meinung, dass bei Aufruf wie es da steht der Main EventLoop verlassen wird und das app-Objekt bei app.exec() den eingegebenen Return-Wert an den return-Befehl aus der Main-Methode weitergibt und somit das ganze beendet.

Ausserdem wir der Konstruktor _or_ app.exec aufgerufen

Code: Alles auswählen

int main ( int argc, char *argv[] )
{
	QApplication app ( argc, argv );
	qDebug() << QCoreApplication::arguments();
	launcher * cdl = new launcher();
	cdl->show();
	return app.exec();
}
wie es bisher in fast allen Beispielen und Anleitungen getan wurde.
Wie kann ich das Programm also zuverlaessig wegballern?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

'Der Neue' hat doch schon gesagt was Du falsch machst...

C-funktion 'exit()' gibts ja auch noch...
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
C167
Beiträge: 105
Registriert: 9. Februar 2008 20:30

Beitrag von C167 »

oehm, naja okay, ich moechte so weit wie moeglich nur Qt-Funktionen verwenden.
Nun braeuchte ich eine Erklaerung, was
Der Konstruktor wird sicher erst nach app.exec() ausgeführt? Nicht, dass du das Objekt schon vorher erstellst, dann hat das natürlich keine Wirkung.
zu bedeuten hat, denn app.exec() blockiert das ganze, und der code nach app.exec() wird erst ausgefuehrt, wenn app.exec() beendet ist.
ausserdem steht in der doku:
int QApplication::exec () [static]
Enters the main event loop and waits until exit() is called, then returns the value that was set to exit() (which is 0 if exit() is called via quit()).
Genau das mache ich ja, ich lege mein Objekt an und starte den event-loop. der soll dann oer QCoreApplication::exit(1); verlassen werden.
Der Neue
Beiträge: 24
Registriert: 31. Mai 2006 14:45

Beitrag von Der Neue »

Ja, alles recht und gut. Aber dein Konstruktor wird ja schon ausgeführt bevor du app.exec() aufrufst, weil du ja dein launcher-Objekt auch schon vorher erstellst. Das heißt dann, dass QCoreApplication::exit(1) aufgerufen wird, obwohl noch überhaupt keine Nachrichtenschleife läuft, weil eben app.exec() vorher nicht aufgerufen wurde.
Gesegnet sein all die, die nichts zu sagen haben
und trotzdem den Mund halten.
C167
Beiträge: 105
Registriert: 9. Februar 2008 20:30

Beitrag von C167 »

Code: Alles auswählen

int ret = app.exec();
launcher * cdl = new launcher();
cdl->show();
return ret;
das qDebug vor alledem geht, aber nach der app.exec-Zeile passiert erwartungsgemaess garnichtsmehr
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Nimm exit() !!!
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
C167
Beiträge: 105
Registriert: 9. Februar 2008 20:30

Beitrag von C167 »

exit schoen und gut, damit funktioniers, danke soweit. Nur wie funktionieren dann die Qt-Funktionen dazu?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Ich gebs auf...
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
C167
Beiträge: 105
Registriert: 9. Februar 2008 20:30

Beitrag von C167 »

gebt mir doch bitte einfach mal ein Beispiel mit einer main-Funktion und einer von QMainWindow abgeleiteten Klasse.
app.exec() blokiert in jedem Fall die Funktion, die es aufruft, welche dann nur fertig abgearbeitet hat wenn app.exec() per QCoreApplication::exit(int) abgebrochen wird oder das ding close aufruft. Ich hab bis jetzt in keinem meiner Buecher ein Beispiel gesehen, bei dem main als letztes etwas anderes enthielt als return app.exec();
C167
Beiträge: 105
Registriert: 9. Februar 2008 20:30

Beitrag von C167 »

die einzige Moeglichkeit, die mir einfaellt ist, die ganze intialisierung zu machen, sobald der user irgendwas macht. Die Initialisierung erfolgt bei mir im konstruktor, und mir ist momentan keine Moeglichkeit bekannt, sie erst auszufuehren wenn der event loop am laufen ist.
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

Aus einem Konstruktor würde ich keine solchen Dinge machen.. zum einen ist das saubere runterfahren da so ne Sache (Objekt wird gerade erstellt), zum anderen sind da komplexere Abläufe nicht sehr schoen umsetzbar (Exceptions, virtuelle Methoden usw.).
Ausserdem ist das Modul nicht sehr gut wiederverwendbar (plötzlicher exit..).

Ich würde es daher erst nach dem Erstellen initialisieren:

Code: Alles auswählen

if (!view->initDatabase())
  shutdown()  // mach was
Wenn du den exit doch in deiner Klasse aufrufen möchtest, würde ich dies in Form eines "lazy loads" implementieren. Also erst bei der ersten Verwendung der Daten (z.B. wenn Model abgefragt wird oder View neu gezeichnet wird etc.) die Datenbank abfragen und gegebenfalls die Applikation beenden.
C167
Beiträge: 105
Registriert: 9. Februar 2008 20:30

Beitrag von C167 »

problem ist, dass, nachdem die Grundoberflaeche angelegt wird, sofort Daten aus der Datenbank kommen _muessen_ und ich darum nicht viele Moeglichkeiten hab, ohne DB etwas zu machen, da die ersten Ansichten schon mit Fehlern um sich werfen und irgendwann SegFault'en

Mit Exceptions gebe ich mich garnicht ab, wenn was schief laeuft, wird knallhart teminiert. Die Anwendung nimmt vom Benutzer ausser dem Druecken auf Knoepfe und Listen keine Eingaben entgegen, und wenn was schief laeuft ist die Sicherheit der Daten gefaerdet. Virtuelle Methoden... kenn ich (noch) nicht, mal suchen...

Nun stellt sich da aber fuer mich eine generelle Designfrage: Wie soll denn eine Initialisierung aussehen? in Main wird ein Objekt einer Klasse angelegt und dessen Konstruktor aufgerufen. der baut die Oberflaeche auf und sobald show() zurueckkehrt wird app.exec() aufgerufen. Ab da ist es nicht mehr Moeglich, der Hauptklasse von "unten" her aus der main heraus irgendetwas zu sagen. Einzige Moeglichkeit die mir einfaellt, ist die:

Code: Alles auswählen

int main(void)
{
// ...
 launcher *cdl = new launcher();
 cdl->show();
 while (true)
 {
  if (cdl->isReady())
  return app.exec();
  }
 }
}
was nicht sehr schoen aussieht
Antworten