よく吹いてください!これは間違って見えたので、自分で試してみる必要がありました。あなたは絶対に正しいです!私は、OS自体(Delphiではなく)で生成されるOS例外(ゼロで割る)であるという事実に絞り込んだ。あなた自身でEIntErrorを試してみると、上記の動作ではなく期待される動作が得られます。予期しない動作は、例外を自分で発生させるたびに発生することに注意してください。
更新:はSystem.pasユニットで例外が再発生した際にコールされる次のコードがある:
{ Destroy any objects created for non-delphi exceptions }
MOV EAX,[EDX].TRaiseFrame.ExceptionRecord
AND [EAX].TExceptionRecord.ExceptionFlags,NOT cUnwinding
CMP [EAX].TExceptionRecord.ExceptionCode,cDelphiException
JE @@delphiException
MOV EAX,[EDX].TRaiseFrame.ExceptObject
CALL TObject.Free
CALL NotifyReRaise
そこで例外は、Delphi例外でない場合(この場合、OS例外)、(変更された) "Delphi"例外が解放され、元の例外が再生成され、例外に対する変更が破棄されます。ケースが閉まった!
更新2:(自分自身を助けることはできませんでした)。次のコードでこれを再現することができます:
type
TThreadNameInfo = record
InfoType: LongWord; // must be $00001000
NamePtr: PAnsiChar; // pointer to message (in user address space)
ThreadId: LongWord; // thread id ($ffffffff indicates caller thread)
Flags: LongWord; // reserved for future use, must be zero
end;
var
lThreadNameInfo: TThreadNameInfo;
with lThreadNameInfo do begin
InfoType := $00001000;
NamePtr := PAnsiChar(AnsiString('Division by zero'));
ThreadId := $ffffffff;
Flags := $00000000;
end;
RaiseException($C0000094, 0, sizeof(lThreadNameInfo) div sizeof(LongWord), @lThreadNameInfo);
楽しんでください!
ありがとうございます。私はプロットを失っていたと思った! – Paul
ゼロ除算はOS例外ではありません。これはハードウェアの例外で、CPU自体によって生成されます(したがって、非同期例外です)。 OSとDelphiの例外はどちらもソフトウェアの例外で、特定のコード呼び出しによって発生します(したがって、同期例外です)。したがって、問題はOSとDelphiの例外ではなく、DelphiとDelphi以外の例外についてです。 "レイズする";元の例外(ハードウェア例外またはソフトウェア例外のいずれか)を再発生させるため、元の例外がDelphiの例外だった場合にのみ、Delphiオブジェクトの変更は保持されます。それはかなり論理的です。 – Alex