1
1.) Behandlung von Laufzeitfehlern in Visual Basic
Laufzeitfehler sind Fehler, die während der Programmausführung (Laufzeit) auftritt. Laufzeitfehler werden in der Regel nicht direkt durch den Programmcode, sondern durch äußere Umstände bedingt (Bsp.: Datenbank bereits von anderen Benutzern exklusiv geöffnet etc.).
Es gibt grundsätzlich 3 Möglichkeiten der Fehlerbehandlung
keine Behandlung, entspricht der Standardfehlerbehandlung durch VB (=Programmabbruch)
verzögerte Behandlung
Sofortige Behandlung mittels Fehlerauffangmechanismus
1.
1) Keine Behandlung
Wenn bei Ausführung des kompilierten Programms (EXE-File) ein Fehler auftritt, dann wird die Fehlermeldung angezeigt und man hat nur mehr die Möglichkeit, das Programm zu beenden (bzw. Im Visual Studio zu debuggen, falls installiert). Die Folge: Nicht gesicherte Daten gehen verloren.
1.2) Verzögerte Behandlung
On Error Resume Next
Schaltet die Standardfehlerbehandlung bis zum Ende der jeweiligen Prozedur aus. Mittels Err-Funktion (ab VB 4.
0 Err-Objekt) kann (jederzeit) festgestellt werden, ob und welcher Fehler aufgetreten ist.
1.3) Sofortige Behandlung
On Error GoTo Marke
Schaltet den Fehlerauffangmechanismus ein
Ist wirksam bis zum Ende der jeweiligen Prozedur oder Funktion
verzweigt bei einem Fehler zum Fehlerbehandlungscode:
ab der Sprungmarke Marke
sinnvoll am Ende der Prozedur
Prozedur wird vorher mittels Exit Sub bzw. Exit Function verlassen.
Err-Objekt liefert Fehlercode, Fehlerbeschreibung etc.
Resume wiederholt fehlerverursachende Anweisung
Resume Next setzt bei der nächsten Anweisung nach der fehlerverursachenden Anweisung fort
1.
4) Allgemeines
Ein Fehlerbehandler wird aktiviert, wenn sich eine On Error GoTo - Anweisung auf ihn bezieht. Wenn ein Fehlerbehandler einmal aktiviert ist, bewirkt jeder Laufzeitfehler, daß die Programmsteuerung zur aktivierten Fehlerbehandlungsroutine springt, und der Fehlerbehandler aktiv wird.
Normalerweise bleibt dieser Mechanismus solange aktiv, bis die Prozedur oder Funktion verlassen wird. Während der Ausführung ist es jedoch möglich, neue Marken als Fehlerbehandlungsroutine zu definieren oder die Fehlerbehandlung gänzlich mit "On Error GoTo 0" auszuschalten.
Tritt ein Fehler in einer Funktion auf, die keine Fehlerbehandlung vorsieht, wird die aufrufende Prozedur nach einer solchen Routine durchsucht. Enthält diese wiederum keine, wird die übergeordnete Prozedur durchsucht usw.
.., bis eine Fehlerbehandlungsroutine gefunden wird oder die oberste Ebene erreicht ist. Bei Resume wird dann die fehlerverursachende (untergeordnete) Funktion/Prozedur nochmals aufgerufen, mit Resume Next wird diese übersprungen.
1.5) Beispiele
1.
5.1 Verzögerte Behandlung
Sub ReadFile(Dateiname As String)
On Error Resume Next
Open Dateiname for Random As 1
If Err.Number = 53 Then
MsgBox "File nicht vorhanden!"
Else
... 'Lesen
End If
End Sub
1.
5.2 Standard-Konstruktion für sofortige Behandlung
Private Sub AnyProcedure (Variablenliste)
On Error Goto Err_Handler
... kritische Anweisungen ..
.
Exit Sub
Err_Handler:
... Anweisungen zur Fehlerbehandlung ..
.
Resume Next 'bzw. Resume oder Exit Sub etc.
End Sub
1.5.3 Konkretes Beispiel: Datenbankbearbeitung
Private Sub Form_Load()
InitListe lstSchueler, App.
Path & "\fstdbn.mdb", "Schueler", "FamName"
End Sub
Private Sub InitListe(Liste As ListBox, DBName As String, RSName As String, _
Field As String)
Dim DB As Database
Dim RS As Recordset
Dim ResumeStatus As Integer 'entscheidet, was nach Fehler passieren soll
On Error GoTo Err_Open_DB '<--
Set DB = DBEngine(0).OpenDatabase(DBName)
On Error GoTo Err_Open_RS '<--
Set RS = DB.OpenRecordset(RSName, dbOpenDynaset)
On Error GoTo Err_Default
Liste.Clear
While Not RS.EOF
Liste.
AddItem RS.Fields(Field)
RS.MoveNext
Wend
Exit Sub
Err_Open_DB:
ResumeStatus = ErrorMsg("Fehler beim Öffnen der Datenbank " & DBName)
GoTo Err_Decide
Err_Open_RS:
ResumeStatus = ErrorMsg("Fehler beim Öffnen der Tabelle " & RSName)
GoTo Err_Decide
Err_Default:
ResumeStatus = ErrorMsg("Fehler beim Füllen der Liste " & Liste.Name)
GoTo Err_Decide
Err_Decide: 'Holzhammer-Methode, in der Praxis differenzieren!
Select Case ResumeStatus
Case vbAbort: End ' <--
Case vbRetry: Resume ' <--
Case vbIgnore: Resume Next ' <--
End Select
End Sub
Public Function ErrorMsg(ErrorTitle As String) As Integer
ErrorMsg = MsgBox(Err.Description, vbAbortRetryIgnore + vbCritical + _ '<--
vbDefaultButton2, ErrorTitle)
End Function
2.) Ausnahmebehandlung (Exception Handling) in C++
Ausnahme = Fehlersituation
Dient zum Behandeln von Fehlern, die nicht an jener Programmstelle, wo sie auftreten, behandelt werden können oder sollen.
throw Beim Erkennen eines Fehlers wird eine Ausnahme ausgeworfen
try Programmteile können überwacht werden, ob bei ihrer Abarbeitung Ausnahmen auftreten.
catch Der Ausnahmebehandler reagiert auf ausgeworfene Ausnahmen, die in einem von try überwachten Programmteil auftreten.
Hinweis: Falls kein catch-Block realisiert wird, wird das Programm abgebrochen.
2.1 Beispiel
char * dupliz (const chat *s)
{
char *neu = new char [strlen(s)+1];
if (neu == NULL)
throw 1; (2)
else
strcpy (neu, s);
return neu;
}
void main()
{
..
.
try { (1)
...
char * s = dupliz("Hallo");
..
.
}
catch (int) { (3)
cout << "Fehler beim Duplizieren: Zu wenig Speicher! " << endl;
}
...
}
2.2 Ablauf
Wenn innerhalb des try-Blockes (1) bzw.
in einer aufgerufenen Funktion (2) eine Ausnahme von Typ Integer ausgeworfen wird, so wird der Ausnahmebehandler catch(int) (3) ausgeführt, der die Ausnahme abfängt.
Wenn keine Ausnahme auftritt, wird kein Ausnahmebehandler ausgeführt.
try-Blöcke sind Anweisungen und können geschachtelt werden.
Direkt anschließend an jeden try-Block muß mindestens ein Ausnahmebehandler (catch-Block) folgen, sinnvollerweise wird für jeden Ausnahmetype, der im try-Block auftreten kann, ein entsprechender Behandler vorgesehen.
Der Code eines catch-Blocks kann nur mittels throw erreicht werden.
2.
3 Unterschiedliche Ausnahmetypen
Im Anschluß an einen try-Block folgen normalerweise eine Liste von mehreren catch-Blöcken.
Welcher catch-Block beim Auftreten einer Ausnahme ausgeführt wird, wird durch den Type der Ausnahme festgelegt (Type hinter dem Schlüsselwort throw)
Ausgeworfene Objekte: beliebige Datentypen, auch benutzerdefinierte Typen (Klassen!) möglich.
Ausgeworfenes Objekt wird so wie ein Parameter an den passenden catch-Block übergeben.
2.4 Fortsetzen des Programmes nach einer Ausnahme
Nach dem Auswerfen einer Ausnahme wird zum nächsten passenden catch-Block verzweigt:
Suche nach dem innersten catch-Block, der noch nicht beendet wurde.
Durchsuchen seiner Behandlerliste nach dem passenden catch-Block.
Wenn keiner vorhanden ist, wird die Suche beim umschließenden catch-Block fortgesetzt.
Wird kein passender catch-Block gefunden, wird das Programm abgebrochen.
Passender catch-Block:
Typ des ausgeworfenen Objektes stimmt exakt mit dem catch-Typ überein, oder
catch-Typ ist eine Basisklasse des ausgeworfenen Objekts, oder
es wurde kein catch-Typ angegeben: catch (...)
Die Behandlerliste eines try-Blocks wird von vorne nach hinten durchsucht, sobald ein passender Behandler gefunden wird, wird die Suche beendet (bei mehreren passenden nur der erste der Liste)
Wenn ein passender Ausnahmebehandler gefunden und abgearbeitet wurde, wird das Programm nach der Behandlerliste fortgesetzt.
Hinweis: Es gibt keine Möglichkeit, zur Auswurfstelle zurückzukehren.
2.5 Fehlerbehandlung mit Fehlerbehandlungs-Klassen
Der Vorteil, wenn für die Fehlerbehandlung mittels Exceptions eine eigene "Fehler"-Klassenhierarchie aufgebaut wird, liegt darin, daß man mittels "catch" auf mehrere Fehler-Auswurfobjekte gleichzeitig abfragen kann.
Wenn ein Auswurfobjekt ein Objekt einer abgeleiteten Klasse ist, wird die Fehlerbehandlugsroutine der Basisklasse durchgeführt.
So kann mit demselben "catch" (der Basisklasse) auf mehrere Auswurfobjekte der abgeleiteten Klassen abgefragt werden. Für eine spezielle Fehlerbehandlung einer abgeleiteten Klasse kann natürlich weiterhin eine eigene Fehlerbehandlung definiert werden.
2.6 Beispiel für Fehlerbehandlungs-Klassen
Klassendefinitionen:
class Ausnahme {
const char *text;
public:
Ausnahme (const char *s) { text = s; }
const char *Text () { return text; }
};
class Fehler_1: public Ausnahme {
public:
Fehler_1() : Ausnahme ("Fehler 1 aufgetrete!") {}
} ;
class Fehler_2: public Ausnahme {
int elem;
public:
Fehler_2 : (int i_elem) : Ausnahme ("Fehler 2 aufgetreten!"), elem (ielem) {}
int Elem() { return elem; }
} ;
Implementierung:
if ...
..
.throw Fehler_1()
...throw Fehler_2(number)
Hautprogramm:
void main ()
{
char ch = ' ';
try {
do {
try {
cout << "Zeichen eingeben:";
cin >> ch;
switch (ch) ..
.
...
..
.
}
catch (Fehler_1 &a) {
cout << a.Text << endl;
}
catch (Fehler_2 &a) {
// Element, bei dem Fehler auftrat, steht nun noch zur Verfügung
// und es können weitere Operationen damit durchgeführt werden
}
} while (ch!='e')
}
catch(Ausnahme &a) { cout << a.Text() << endl; }
catch(...
) {cpit << "Unerwartete Ausnahme aufgetreten!"; }
}
Anmerkungen: |
| impressum | datenschutz
© Copyright Artikelpedia.com