OCCI / Unbekannter Fehler / Errorhandling?!

Nospherates

Erfahrenes Mitglied
Hallo zusammen!
Im Zuge eines Datenbankwechsels von mySQL nach Oracle musste auch eine C- Anwendung umgeschrieben werden. Unter mySQL lief soweit alles problemlos, seitdem nun OCCI mit eingebunden wurde stürzt das Programm mehr oder minder regelmäßig ab. Ich konnte das zumindest soweit eingrenzen, dass ich IN ETWA die Stelle abstecken kann wo es passiert. Allerdings wirkt es trotzdem manchmal willkürlich, weil die Stelle des Absturzes etwas variiert. Es passiert aber immer im selben Abschnitt des Programms.

Die Funktion führt eine simple Select Anweisung aus und soll die Ergebnisse anschließend in einen vector schreiben. Das klapp grundsätzlich auch, allerdings stürzt das Programm meistens "string value=rs->getString(i);" (Zeile 20) an dieser Stelle ab. Jedoch nicht direkt beim ersten Schleifendurchgang, sondern eher beim letzten. Zwischendurch ist er mir auch mal abgeschmiert wenn das Resultset durchgelaufen ist, aber bevor er die Schleife verlässt.

Ich hab keine Ahnung mehr wo ich noch ansetzen soll, der Try-catch Block greift auch nicht, so dass ich keine Auskunft erhalte was da eigentlich schief läuft. Ich bezweifel, dass mir jemand direkt eine Lösung nennen kann, aber hat vielleicht noch jemand eine Ahnung was für Fehler man noch abfangen könnte, so dass ich zumindest mal eine Meldung erhalte?!

Für mich sieht es entweder nach einem Speicherproblem oder einem Verbindungsproblem aus, vor allem weil bei mehrfachen Start der Anwendung es irgendwann auch einmal durchläuft.

Vielen Dank schonmal....

Der Code der Funktion sieht wie folgt aus:


Code:
BOOL CoraDB::getValues(CString query, int col, std::vector<CString>& vecReturn){
	myFunctions.createLogEntry("Try: "+query,0,3);
	BOOL isOk=FALSE, isEmpty=TRUE;
	ResultSet* rs;
	Statement* stmt;
	CT2CA pszConvertedAnsiString (query); 
	std::string stdquery (pszConvertedAnsiString); 
	stmt = conn->createStatement();
	stmt->setSQL(stdquery);

	try{
		rs = stmt->executeQuery();
		cout <<" Results: " <<rs->getNumArrayRows() << " / cols: " << myFunctions.getNumAsText(col) << endl;
		while (rs->next() ){
			myFunctions.createLogEntry("Before for",0,5);
			for (int i = 1; i <= col; i++){
				isEmpty=FALSE;
				isOk=FALSE;
				myFunctions.createLogEntry("Before getString",0,5);
				string value=rs->getString(i);
				myFunctions.createLogEntry("After getString",0,5);
				vecReturn.push_back(value.c_str());
				myFunctions.createLogEntry("Value pushed "0,5);
				isOk=TRUE;
				myFunctions.createLogEntry("isOk",0,5);
			}//for
			myFunctions.createLogEntry("After for",0,5);
		}//while		
		//rs->cancel();
		myFunctions.createLogEntry("Succeed: "+query,0,3);
		stmt->closeResultSet(rs);
		conn->terminateStatement(stmt);
		if (isOk || isEmpty)
			return TRUE;
		else{
			myFunctions.createLogEntry("Es ist ein unbekannter Fehler (CoraDB::getValues() aufgetreten!");
			return FALSE;
		}
		return TRUE;
	}
	catch (SQLException &e){
		myFunctions.createLogEntry("Es ist ein SQLFehler (CoraDB::getValues() aufgetreten! " + e.getErrorCode());
		return FALSE;
	}catch (exception &ex){
		CString cstError=ex.what();
		myFunctions.createLogEntry(_T("Es ist ein Fehler (CoraDB::getValues() aufgetreten! ") +cstError );
		return FALSE;
	}
	return FALSE;

}
 
Hi!
Richtig, das Programm schmiert mit einem nichtssagenden Application-Error Eintrag im Ereignislog ab. Die Maßnahmen in den Catch Blöcken werden nicht ausgeführt.
Wenn ich den String vorher ins Log schreibe oder auf der Konsole ausgeben, wird er ordnungsgemäß angezeigt. Da es eben auch ab und an funktioniert kann ein leerer String eigentlich nicht das Problem sein. Aber falls doch, wie kann ich das abfangen? In Java kann man ja auf null prüfen... bei C kennt der Compiler null nicht?! Eine Nullpointerexception gibt es ja scheinbar auch nicht...
 
Wenn es unter Windows läuft ist die Méglichkeit vorhanden, dass dir das Betriebssystem einen kritischen Fehler via RaiseException mitteilt. Du kannst diese via __try __except abfangen.
 
Danke für die Antwort, aber kommt leider das gleiche bei rum. Ich hab statt dem try Block nun __try benutzt, aber auch dort geht er nicht in den __except Block. Und ja es läuft unter Windows Server 2003.
 
Dann stürzt dein Programm aber auch nicht da ab (in den __except-Block gehts nur, wenn du in __except EXCEPTION_EXECUTE_HANDLER zurückgibst), ausser du zerstörst in dem Block dein System so komplett dass das OS keine Möglichkeit mehr sieht auch nur eine einzige Instruktion ausführen zu können, das ist aber im Usermode praktisch unmöglich.
 
Ich hab/hatte den Code wie unten angegeben abgeändert. Mag sein, dass ich da noch was falsch gemacht hab?! Mit __try hab ich noch nicht gearbeitet und mich an der Hilfe orientiert.

Das Log schreibt aber auch bei der Variante bis "Before getString" und beendet sich danach ohne die Ausgabe die im __except Block ausgeführt werden sollte. Wo sollte der Fehler sonst auftreten, außer in diesem Block?

Code:
	__try{
		rs = stmt->executeQuery();
		while (rs->next() ){
			myFunctions.createLogEntry("Before for",0,5);
			for (int i = 1; i <= col; i++){
				isEmpty=FALSE;
				isOk=FALSE;
				myFunctions.createLogEntry("Before getString",0,5);
				cout << rs->getString(i)<<endl;
				string value=rs->getString(i);
				myFunctions.createLogEntry("After getString",0,5);
				vecReturn.push_back(value.c_str());
				myFunctions.createLogEntry("Value pushed "+myFunctions.getNumAsText(i),0,5);
				isOk=TRUE;
				myFunctions.createLogEntry("isOk",0,5);
			}//for
			myFunctions.createLogEntry("After for",0,5);
		}//while		
		//rs->cancel();
	}__except(GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
	{
		cout << "FEHLER" << endl;
		return FALSE;
	}
 
Ah, ok, also das funktioniert folgendermassen:
Innerhalb der Klammern von __except musst du dem OS angeben, was es tun soll. EXCEPTION_EXECUTE_HANDLER sagt, dass der Handlercode ausgeführt werden soll (der Block unter __except). EXCEPTION_CONTINUE_SEARCH sagt dass weiter in der Liste der SEH gesucht werden soll.

In deinem Fall wird der Handler nur dann ausgeführt wenn eine Division durch 0 stattgefunden hat.

Um zu wissen ob es sich mal grundsätzlich um einen Fehler handelt, der abgefangen werden kann kannst du __except(EXCEPTION_EXECUTE_HANDLER) einfügen, dann wird der Handler immer ausgeführt. Falls dann die Ausgabe erfolgt kann man dann weiter schauen, was die Ursache ist.
 
Danke! .. jetzt funktioniert das auch, sprich der gibt mit auf der Konsole "FEHLER" aus. Ich hab das ganze jetzt noch um ne kleine Fehlerbehandlung ergänzt und bekomme auch den Errorcode ausgegeben. Das ist nun zwar ne schön lange Zahl + eine Adresse, aber wirklich weiter komm ich damit auch noch nicht. Gibt es irgendeine Möglichkeit über den Weg auch einen Text herauszubekommen? Momentan sieht das so aus:

Aufruf:
Code:
__except(errorOutput(GetExceptionCode(), GetExceptionInformation()))

Funktion:
Code:
int CoraDB::errorOutput(unsigned int code, struct _EXCEPTION_POINTERS *ep) {
	cout << "ERROR Nummer: " << code << endl;
	cout << "ERROR Meldung: " << ep->ExceptionRecord->ExceptionInformation << endl;
	return 0;
}
 
Die Nummer, die du erhälst ist ein Exceptioncode. Diese findest du dann auch alle in der MSDN beschrieben. Siehe Hier. Die ExceptionInformation's sind nicht genormt und du solltest sie daher auch nicht pauschal verwenden. Ich bin grad zeitlich etwas eingeschränkt und verweise daher mal vorerst auf einen Blogpost von mir in dem ich bisschen was über Exceptionhandling unter Windows geschrieben habe. Es ist eigentlich nur ein Einstieg und nicht ganz gleich mit deiner Situation, aber die EXCEPTION_POINTERS hast du ja auch. Werde dann später noch etwas mehr dazu schreiben:
Blog
 
Zurück