Wenn man mit richtigen Delphi-Exceptions arbeitet, dann erstellt man ja oft auch erst kurz vorher noch das
Exception-Object
und beim Erstellen eines Objektes und dem zusammenbauen von Strings, läuft genug ab, um Alles zu verändern.
Ausnahme, man macht es wie beim EOutOfMemory, wo das Objekt bereits vorher erstellt wurde
(klar, weil ja praktisch der RAM schon voll ist und kein Speicher mehr zum Erstellen frei sein könnte)
und braucht dann "nur" noch das
Raise
, womit aber dennoch mindestens ein EAX verändert wird, um das Objekt zu übergeben.
Bleiben also nur noch die
OS-Exceptions, wie AccessViolation oder DivisionByZero, was man nahezu direkt auslösen könnte.
Beim Letztem wird zwar oft auch mit mindestens einem Wert in den Registern gerechnet, aber da könnte man "irgendwas" nehmen, war grade in den Registern steht und die NULL kommt vom Heap/Stack.
Aber auch hier wieder das Problem, dass im
ExceptionRecord von Windows keine Register drin sind und man somit auch erst wieder Code in der Fehlerbehandlung braucht, um die Register auszulesen,
was nur ginge, wenn das in einem anderen Thread passiert.
Delphi-Quellcode:
EExternal =
class(
Exception)
public
{$IFDEF MSWINDOWS}
ExceptionRecord: PExceptionRecord
platform; <<<<<<<<<<<<<<<<<<<<<<<<<<<<
{$ENDIF}
{$IF defined(LINUX) or defined(MACOS) or defined(ANDROID)}
ExceptionAddress: LongWord
platform;
AccessAddress: LongWord
platform;
SignalNumber: Integer
platform;
{$ENDIF}
end;
EExternalException =
class(EExternal);
EIntError =
class(EExternal);
EDivByZero =
class(EIntError);
ERangeError =
class(EIntError);
EIntOverflow =
class(EIntError);
EMathError =
class(EExternal);
EInvalidOp =
class(EMathError);
EZeroDivide =
class(EMathError);
EOverflow =
class(EMathError);
EUnderflow =
class(EMathError);
EAccessViolation =
class(EExternal); <<<<<<<<<<<<<
EPrivilege =
class(EExternal);
EStackOverflow =
class(EExternal)
end deprecated;
EControlC =
class(EExternal);
Delphi-Quellcode:
try
...
Pointer(
nil) := 666;
except
on E:
Exception do begin
// für GetThreadContext wäre es hier schon zu spät
// aber E.ExceptionRecord wäre aber noch verfügbar
end;
end;
Noch etwas früher kommt man in die Fehlerbehandlung rein, wenn man die Registrierungsstellen in
Exception/SysUtils/System benutzt,
aber auch da wird vorher immer noch etwas Code ausgeführt.