var LResult:Variant;
//......你在该函数内部需要创建的各类型的实例
try
try
//......写与这些创建的各类型的实例相关的代码
except
//......进入异常处理:
on E: ESafecallException do ; //:比方
on E: EObjectDisposed do ; //:比方
on E: EAccessViolation do ; //:比方
on E: EOSError do ; //:比方
on E: EExternalException do ; //:比方
on E: EExternal do ; //:比方
else //:比方
begin
//......如果有if或case语句:
//......如果有异常返回值,给它赋值LResult:=....;
//:彻底释放函数内部创建的引用参照的实例,注意引用参照ARC的类型的释放,具体看该类型的构造函数和解构函数;注意不要误解了“Delphi10.4.2及其后续版本会放弃ARC”的错误提法,其本意是说,原来的处理方式保持不变,$NextGen下一代,新的控件、新的组件、新类型或新的函数,不再在其内部构造ARC的关系啦。若遇TNetHTTPClient的实例的释放,请用MyHTTPClient.DisposeOf;//而不要使用Free;或Destroy;因为你可能将其使用在ARC环境下引用了。
//:若遇TNetHTTPClient的实例的释放:MyHTTPClient.DisposeOf;
end;
//......如果有异常返回值,返回:Result:=LResult;
exit;//:非常重要,不要试图将其留给fanally子句;事实上,当遇到异常except被中断时,是不会退出fanally的,进程始终保持在fanally的输入阶段并不会让fanally进行任何输出;故而exit之前异常处理一定要释放干净,否则即便用户UI交互后内部仍然会有内存泄漏。
end;
//......没有遇到异常的其它代码段:
//......如果有if或case语句:
//......如果有返回值,给它赋值LResult:=....;
//......如果有返回值,返回:Result:=LResult;
finally
//:彻底释放函数内部创建的各类型的实例;同时注意引用参照ARC的类型的释放,具体看该类型的构造函数和解构函数;注意不要误解了“Delphi10.4.2及其后续版本会放弃ARC”的错误提法,其本意是说,原来的处理方式保持不变,$NextGen下一代,新的控件、新的组件、新类型或新的函数,不再在其内部构造ARC的关系啦。若遇TNetHTTPClient的实例的释放,请用MyHTTPClient.DisposeOf;//而不要使用Free;或Destroy;因为你可能将其使用在ARC环境下引用了。
//:若遇TNetHTTPClient的实例的释放:if MyHTTPClient<>nil then MyHTTPClient.DisposeOf;
end;
2、运行时刻库基础的except异常类型及中断信号
//System.SysUtils.pas :
{$IFDEF POSIX}
TEraRange = record
StartDate : Integer; // whole days since 12/31/1899 (TDateTime basis)
EndDate : Integer; // whole days since 12/31/1899 (TDateTime basis)
end deprecated 'Use EraInfo in TFormatSettings';
{$ENDIF}
{ Exceptions }
PExceptionRecord = System.PExceptionRecord;
Exception = class(TObject)
private
FMessage: string;
FHelpContext: Integer;
FInnerException: Exception;
FStackInfo: Pointer;
FAcquireInnerException: Boolean;
class constructor Create;
class destructor Destroy;
protected
procedure SetInnerException;
procedure SetStackInfo(AStackInfo: Pointer);
function GetStackTrace: string;
// This virtual function will be called right before this exception is about to be
// raised. In the case of an external non-Delphi exception, this is called soon after
// the object is created since the "raise" condition is already in progress.
procedure RaisingException(P: PExceptionRecord); virtual;
public
constructor Create(const Msg: string);
constructor CreateFmt(const Msg: string; const Args: array of const);
{$IFNDEF NEXTGEN}
constructor CreateRes(Ident: NativeUInt); overload;
{$ENDIF !NEXTGEN}
constructor CreateRes(ResStringRec: PResStringRec); {$IFNDEF NEXTGEN} overload; {$ENDIF !NEXTGEN}
{$IFNDEF NEXTGEN}
constructor CreateResFmt(Ident: NativeUInt; const Args: array of const); overload;
{$ENDIF !NEXTGEN}
constructor CreateResFmt(ResStringRec: PResStringRec; const Args: array of const); {$IFNDEF NEXTGEN} overload; {$ENDIF !NEXTGEN}
constructor CreateHelp(const Msg: string; AHelpContext: Integer);
constructor CreateFmtHelp(const Msg: string; const Args: array of const;
AHelpContext: Integer);
{$IFNDEF NEXTGEN}
constructor CreateResHelp(Ident: NativeUInt; AHelpContext: Integer); overload;
{$ENDIF !NEXTGEN}
constructor CreateResHelp(ResStringRec: PResStringRec; AHelpContext: Integer); {$IFNDEF NEXTGEN} overload; {$ENDIF !NEXTGEN}
constructor CreateResFmtHelp(ResStringRec: PResStringRec; const Args: array of const;
AHelpContext: Integer); {$IFNDEF NEXTGEN} overload; {$ENDIF !NEXTGEN}
{$IFNDEF NEXTGEN}
constructor CreateResFmtHelp(Ident: NativeUInt; const Args: array of const;
AHelpContext: Integer); overload;
{$ENDIF !NEXTGEN}
destructor Destroy; override;
function GetBaseException: Exception; virtual;
function ToString: string; override;
property BaseException: Exception read GetBaseException;
property HelpContext: Integer read FHelpContext write FHelpContext;
property InnerException: Exception read FInnerException;
property Message: string read FMessage write FMessage;
property StackTrace: string read GetStackTrace;
property StackInfo: Pointer read FStackInfo;
class var
// Hook this function to return an opaque data structure that contains stack information
// for the given exception information record. This function will be called when the
// exception is about to be raised or if this is an external exception such as an
// Access Violation, called soon after the object is created.
GetExceptionStackInfoProc: function (P: PExceptionRecord): Pointer;
// This function is called to return a string representation of the above opaque
// data structure
GetStackInfoStringProc: function (Info: Pointer): string;
// This function is called when the destructor is called to clean up any data associated
// with the given opaque data structure.
CleanUpStackInfoProc: procedure (Info: Pointer);
// Use this function to raise an exception instance from within an exception handler and
// you want to "acquire" the active exception and chain it to the new exception and preserve
// the context. This will cause the FInnerException field to get set with the exception
// in currently in play.
// You should only call this procedure from within an except block where the this new
// exception is expected to be handled elsewhere.
class procedure RaiseOuterException(E: Exception); static;
// Provide another method that does the same thing as RaiseOuterException, but uses the
// C++ vernacular of "throw"
class procedure ThrowOuterException(E: Exception); static;
end;
EArgumentException = class(Exception);
EArgumentOutOfRangeException = class(EArgumentException);
EArgumentNilException = class(EArgumentException);
EPathTooLongException = class(Exception);
ENotSupportedException = class(Exception);
EDirectoryNotFoundException = class(Exception);
EFileNotFoundException = class(Exception);
EPathNotFoundException = class(Exception);
EListError = class(Exception);
EInvalidOpException = class(Exception);
ENoConstructException = class(Exception);
ExceptClass = class of Exception;
EAbort = class(Exception);
EHeapException = class(Exception)
{$IFNDEF AUTOREFCOUNT}
private
AllowFree: Boolean;
{$ENDIF}
protected
procedure RaisingException(P: PExceptionRecord); override;
public
{$IFNDEF AUTOREFCOUNT}
procedure FreeInstance; override;
{$ENDIF}
end;
EOutOfMemory = class(EHeapException);
EInOutError = class(Exception)
public
ErrorCode: Integer;
end;
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 LINUX or MACOS}
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);
EInvalidPointer = class(EHeapException);
EInvalidCast = class(Exception);
EConvertError = class(Exception);
EAccessViolation = class(EExternal);
EPrivilege = class(EExternal);
EStackOverflow = class(EExternal)
end deprecated;
EControlC = class(EExternal);
{$IF defined(LINUX) or defined(MACOS) or defined(ANDROID)}
EQuit = class(EExternal) end platform;
{$ENDIF}
{$IFDEF POSIX}
ECodesetConversion = class(Exception) end platform;
{$ENDIF POSIX}
EVariantError = class(Exception);
EPropReadOnly = class(Exception);
EPropWriteOnly = class(Exception);
EAssertionFailed = class(Exception);
EAbstractError = class(Exception);
EIntfCastError = class(Exception);
EInvalidContainer = class(Exception);
EInvalidInsert = class(Exception);
EPackageError = class(Exception);
ECFError = class(Exception);
EOSError = class(Exception)
public
ErrorCode: DWORD;
end;
{$IFDEF MSWINDOWS}
EWin32Error = class(EOSError)
end deprecated;
{$ENDIF}
ESafecallException = class(Exception);
EMonitor = class(Exception);
EMonitorLockException = class(EMonitor);
ENoMonitorSupportException = class(EMonitor);
EProgrammerNotFound = class(Exception);
ENotImplemented = class(Exception);
EObjectDisposed = class(Exception);
EOperationCancelled = class(Exception);
{$IFDEF ANDROID}
EJNIException = class(Exception)
public
ExceptionClassName: string;
constructor CreateWithClassName(const JNIExceptionClassName: string; const Msg: string);
end;
{$ENDIF}
{$IF defined(LINUX) or defined(MACOS) or defined(ANDROID)}
{
Signals
External exceptions, or signals, are, by default, converted to language
exceptions by the Delphi RTL. Under Linux, a Delphi application installs
signal handlers to trap the raw signals, and convert them. Delphi libraries
do not install handlers by default. So if you are implementing a standalone
library, such as an Apache DSO, and you want to have signals converted to
language exceptions that you can catch, you must install signal hooks
manually, using the interfaces that the Delphi RTL provides.
For most libraries, installing signal handlers is pretty
straightforward. Call HookSignal(RTL_SIGDEFAULT) at initialization time,
and UnhookSignal(RTL_SIGNALDEFAULT) at shutdown. This will install handlers
for a set of signals that the RTL normally hooks for Delphi applications.
There are some cases where the above initialization will not work properly:
The proper behaviour for setting up signal handlers is to set
a signal handler, and then later restore the signal handler to its previous
state when you clean up. If you have two libraries lib1 and lib2, and lib1
installs a signal handler, and then lib2 installs a signal handler, those
libraries have to uninstall in the proper order if they restore signal
handlers, or the signal handlers can be left in an inconsistent and
potentially fatal state. Not all libraries behave well with respect to
installing signal handlers. To hedge against this possibility, and allow
you to manage signal handlers better in the face of whatever behaviour
you may find in external libraries, we provide a set of four interfaces to
allow you to tailor the Delphi signal handler hooking/unhooking in the
event of an emergency. These are:
InquireSignal
AbandonSignalHandler
HookSignal
UnhookSignal
InquireSignal allows you to look at the state of a signal handler, so
that you can find out if someone grabbed it out from under you.
AbandonSignalHandler tells the RTL never to unhook a particular
signal handler. This can be used if you find a case where it would
be unsafe to return to the previous state of signal handling. For
example, if the previous signal handler was installed by a library
which has since been unloaded.
HookSignal/UnhookSignal setup signal handlers that map certain signals
into language exceptions.
See additional notes at InquireSignal, et al, below.
}
const
RTL_SIGINT = 0; // User interrupt (SIGINT)
{$IFDEF MACOS}
RTL_SIGQUIT = 1; // User interrupt (SIGQUIT)
{$ENDIF MACOS}
{$IF Defined(LINUX) or Defined(ANDROID)}
RTL_SIGFPE = 1; // Floating point exception (SIGFPE)
RTL_SIGSEGV = 2; // Segmentation violation (SIGSEGV)
RTL_SIGILL = 3; // Illegal instruction (SIGILL)
RTL_SIGBUS = 4; // Bus error (SIGBUS)
RTL_SIGQUIT = 5; // User interrupt (SIGQUIT)
{$ENDIF LINUX}
RTL_SIGLAST = RTL_SIGQUIT; // Used internally. Don't use this.
RTL_SIGDEFAULT = -1; // Means all of a set of signals that the we capture
// normally. This is currently all of the preceding
// signals. You cannot pass this to InquireSignal.
type
{ TSignalState is the state of a given signal handler, as returned by
InquireSignal. See InquireSignal, below.
}
TSignalState = (ssNotHooked, ssHooked, ssOverridden);
var
{
If DeferUserInterrupts is set, we do not raise either SIGINT or SIGQUIT as
an exception, instead, we set SIGINTIssued or SIGQUITIssued when the
signal arrives, and swallow the signal where the OS issued it. This gives
GUI applications the chance to defer the actual handling of the signal
until a time when it is safe to do so.
}
DeferUserInterrupts: Boolean;
SIGINTIssued: Boolean;
SIGQUITIssued: Boolean;
{$IF Defined(EXTERNALLINKER)}
DeferSegmentationViolation: Boolean;
SIGSEGVIssued: Boolean;
SIGSEGVFaultInstPtr: NativeUInt;
SIGSEGVFaultAddrPtr: NativeUInt;
procedure CheckAndClearSIGSEGV;
{$ENDIF EXTERNALLINKER}
{$ENDIF LINUX or MACOS or ANDROID}
{$IF Defined(LINUX) or Defined(ANDROID)}
{$IF Defined(LINUX64) and Defined(CPUX64)}
function MapFPE(Context: IntPtr; Code:Integer): TRuntimeError;
{$ELSE}
function MapFPE(Context: IntPtr): TRuntimeError;
{$ENDIF}
{$NODEFINE MapFPE}
function MapFault(Context: IntPtr): TRuntimeError;
{$NODEFINE MapFault}
{$ENDIF LINUX or ANDROID}