šHgeocities.com/Vienna/Stage/4793/excp7.htmgeocities.com/Vienna/Stage/4793/excp7.htmdelayedxŲ¸ÕJ˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙Č0¤£g&OKtext/html€Cmog&˙˙˙˙b‰.HMon, 18 Dec 2000 15:42:10 GMTēMozilla/4.5 (compatible; HTTrack 3.0x; Windows 98)en, *Ų¸ÕJg& Ein Beispiel

Zurück ] Nach oben ] Weiter ]

 

Ein Beispiel (SEH 01)

#include <stdio.h>
#include "windows.h"
#define filter(level, status) \
    ( \
    printf("%s:%*sfilter => %s\n", \
    #level, (int) (2 * (level)), "", #status), \
    (status) \
)  

#define termination_trace(level) \
    printf("%s:%*shandling %snormal termination\n", \
    #level, (int) (2 * (level)), "", \
    AbnormalTermination() ? "ab" : "")
    
static void trace(int level, char const *message)
{  
    printf("%d:%*s%s\n", level, 2 * level, "", message);
}  

extern int main(void)

    DWORD const code = 0xE0000001;
    trace(0, "before first try");
    __try {
        trace(1, "try");
        __try {
            trace(2, "try");
            __try { 
                trace(3, "try");
                __try{
                    trace(4, "try");
                    trace(4, "raising exception");
                    RaiseException(code, 0, 0, 0); // !!!
                    trace(4, "after exception");
                }
                __finally {
                    termination_trace(4);
                }
                trace(3, "continuation");
            }
            __except(filter(3, EXCEPTION_CONTINUE_SEARCH))
            {
                trace(3, "handling exception");
            }
            trace(2, "continuation");
        }
        __finally {
            termination_trace(2);
        }
    trace(1, "continuation");
    }
    __except(filter(1, EXCEPTION_EXECUTE_HANDLER))
    {
        trace(1, "handling exception");
    }
    trace(0, "continuation");
    return 0;
}
  • Das Programm hat vier verschachtelte try-Blöcke. Zwei haben Exceptionhandler, zwei haben einen Terminationhandler. Der verantwortliche Programmierer ( von M...) entschuldigt die Unübersichtlichkeit mit der Erklärung, alles in einem Block in einer Funktion zu demonstrieren. In Produktionscode sollte man solche Blöcke in mehreren Funktionen kodieren.

  • Da der Verlauf getraced wird, zeigt der Output den aktuellen Schachtelungsgrad.

  • Die Exceptionfilter sind durch das Makro filter implementiert. Der erste Parameter ist die Schachtelungstiefe, der zweite der tatsächliche Fehlercode.

  • Die Terminationhandler tracen ihre Verarbeitung mit dem Makro termination_trace, welches ausgibt, wie der Handler aufgerufen wurde. Es muss ja nicht eine Exception sein!

Folgender Output wird erzeugt:

0:before first try
1:  try
2:    try
3:      try
4:        try
4:        raising exception
3:      filter => EXCEPTION_CONTINUE_SEARCH
1:  filter => EXCEPTION_EXECUTE_HANDLER
4:        handling abnormal termination
2:    handling abnormal termination
1:  handling exception
0:continuation

Folgendes ist passiert:

  • Der try-Block Nummer 4 wirft eine userdefinierte Exception. Dies setzt eine Suche nach einem Exceptionfilter in Gang, der bereit ist diese Exception zu bearbeiten.

  • Der erste Exceptionhandler ( Nummer 3) liefert den Wert EXCEPTION_CONTINUE_SEARCH und verweigert somit seine Mitarbeit. Also geht die Suche weiter.

  • Der nächst Filter ( Nummer 1) liefert den Filter EXCEPTION_EXECUTE_HANDLER. Diesmal wird die Exception gefangen. Der Filter zeigt an, daß dies eine terminating exception ist.

  • Nun kehrt das Programm zurück an die Stelle, an der es gerufen wurde, und der Stack wird zurückgespult. Auf dem Weg werden alle Terminationhandler aufgerufen bis der Handler, der die Ausnahme gefangen hat, gefunden wird. Während dem Zurückspulen, wird nur der Code in den Terminationhandlern ausgeführt - kein anderer.

  • Nun geht es normal nach dem Exceptionhandler (Nummer 1) weiter.

Hinweis: Wie man sieht, wird der Stack zweimal durchlaufen: einmal, um einen Exceptionhandler zu finden und dann noch mal, um die evtl. Terminationhandler aufzurufen. Hier ergibt sich eine Fehlerquelle, wenn ein Exceptionhandler irgend etwas tut, was einen darunterliegenden Terminationhandler durcheinander bringt. Deswegen sollte man Seiteneffekte in Filtern vermeiden. Falls man trotzdem welche braucht, so sollte man die Terminationhandler davor schützen.