(EClass: ESafecallException; EIdent: SSafecallException) );
function GetExceptionClass(P: PExceptionRecord): ExceptClass; var
ErrorCode: Byte; begin
ErrorCode := Byte(MapException(P)); Result := ExceptMap[ErrorCode].EClass; end;
{ cContinuable = 0; } { cNonContinuable = 1; } { cUnwinding = 2; } { cUnwindingForExit = 4; } { cUnwindInProgress = cUnwinding or cUnwindingForExit; }
{ SysUtils.pas }
function GetExceptionObject(P: PExceptionRecord): Exception; var
ErrorCode: Integer;
function CreateAVObject: Exception; var
AccessOp: string; // string ID indicating the access type READ or WRITE AccessAddress: Pointer;
MemInfo: TMemoryBasicInformation; ModName: array[0..MAX_PATH] of Char; begin
with P^ do begin
if ExceptionInformation[0] = 0 then AccessOp := SReadAccess else
AccessOp := SWriteAccess;
AccessAddress := Pointer(ExceptionInformation[1]);
VirtualQuery(ExceptionAddress, MemInfo, SizeOf(MemInfo)); if (MemInfo.State = MEM_COMMIT) and
(GetModuleFileName(THandle(MemInfo.AllocationBase), ModName, SizeOf(ModName)) <> 0) then
Result := EAccessViolation.CreateFmt(sModuleAccessViolation, [ExceptionAddress, ExtractFileName(ModName), AccessOp, AccessAddress]) else
Result := EAccessViolation.CreateFmt(SAccessViolationArg3, [ExceptionAddress, AccessOp, AccessAddress]); end; end;
begin
ErrorCode := Byte(MapException(P)); case ErrorCode of 3..10, 12..21:
with ExceptMap[ErrorCode] do Result := EClass.Create(EIdent); 11: Result := CreateAVObject; else
Result := EExternalException.CreateFmt(SExternalException, [P.ExceptionCode]);
end;
if Result is EExternal then EExternal(Result).ExceptionRecord := P; end;
=============================================================================== ⊙ try...except 的编译器实现
===============================================================================
测试代码: begin try
raise Exception.Create('Exception'); except
on E: Exception do begin
ShowMessage(E.Message); end; end; end;
Unit1.pas.28: begin
004520C0 55 push ebp 004520C1 8BEC mov ebp,esp
004520C3 51 push ecx // 生成异常变量 E 的堆栈空间 004520C4 53 push ebx 004520C5 56 push esi 004520C6 57 push edi
Unit1.pas.29: try
// 以下 5 行在堆栈中生成异常处理结构 (try 指令的编译器实现) 004520C7 33C0 xor eax,eax
004520C9 55 push ebp // 设置 TExcFrame.hEBP 004520CA 68F5204500 push $004520f5 // 设置 TExcFrame.desc 004520CF 64FF30 push dword ptr fs:[eax] // 设置 TExcFrame.next 004520D2 648920 mov fs:[eax],esp // 安装 新建的异常处理结构
Unit1.pas.30: raise Exception.Create('Exception');
004520D5 B928214500 mov ecx,$00452128 // 错误信息字符串的地址 004520DA B201 mov dl,$01
004520DC A1286D4000 mov eax,[$00406d28] // Exception 类的 VMT ptr 004520E1 E86A91FBFF call Exception.Create
004520E6 E89D17FBFF call @RaiseExcept // raise 的编译器实现
// 以下 5 行恢复上面安装的的异常处理结构 (try 指令的编译器实现) 004520EB 33C0 xor eax,eax
004520ED 5A pop edx // TExcFrame.next(原结构地址) 004520EE 59 pop ecx 004520EF 59 pop ecx
004520F0 648910 mov fs:[eax],edx
004520F3 EB24 jmp +$24 (00452119) // 退出 try...except 块
// 以下 6 行是编译器生成的 TExeDesc 结构 (try 指令的编译器实现)
004520F5 E9CE15FBFF jmp @HandleOnException // 异常发生时的处理函数 004520FA 0100 add [eax],eax // ?? 004520FC 0000 add [eax],al 004520FE 286D40 sub [ebp+$40],ch 00452101 0006 add [esi],al
00452103 214500 and [ebp+$00],eax
Unit1.pas.32: on E: Exception do
00452106 8945FC mov [ebp-$04],eax
Unit1.pas.34: ShowMessage(E.Message);
00452109 8B45FC mov eax,[ebp-$04] 0045210C 8B4004 mov eax,[eax+$04] 0045210F E85052FDFF call ShowMessage 00452114 E8EB17FBFF call @DoneExcept 00452119 5F pop edi 0045211A 5E pop esi 0045211B 5B pop ebx 0045211C 59 pop ecx 0045211D 5D pop ebp 0045211E C3 ret