异常消息从何而来?
Where does exception message comes from?
当出现 EZeroDivide
、EOverflow
、EMathError
... 等异常时,它们会显示一条默认消息。
例如,以下代码引发 EZeroDivide
并显示以下消息:
Floating point division by zero
procedure TForm1.Button1Click(Sender: TObject);
var
N : Extended;
D : Extended;
begin
N := 100;
D := 0;
Caption := FloatToStr(N/D);
end;
当我 "manually" 通过代码引发 EZeroDivide
异常时,我必须将 Msg
参数传递给构造函数并将其作为 EZeroDivide
异常引发有一个空字符串消息:
procedure TForm1.Button2Click(Sender: TObject);
begin
raise EZeroDivide.Create('');
end;
默认异常消息从何而来?
那些异常实例是由 RTL 内部生成的。问题中的具体字符串可以在SysConst.pas
的resourcestring
部分找到
SZeroDivide = 'Floating point division by zero';
RTL 在内部使用 Error
方法来引发此类异常。运行时错误的完整列表在以下枚举的 System
单元中定义:
TRuntimeError = (reNone, reOutOfMemory, reInvalidPtr, reDivByZero,
reRangeError, reIntOverflow, reInvalidOp, reZeroDivide, reOverflow,
reUnderflow, reInvalidCast, reAccessViolation, rePrivInstruction,
reControlBreak, reWhosebug,
{ reVar* used in Variants.pas }
reVarTypeCast, reVarInvalidOp,
reVarDispatch, reVarArrayCreate, reVarNotArray, reVarArrayBounds,
reAssertionFailed,
reExternalException, { not used here; in SysUtils }
reIntfCastError, reSafeCallError,
reMonitorNotLocked, reNoMonitorSupport
{$IF defined(LINUX) or defined(MACOS) or defined(ANDROID)}
, reQuit
{$ENDIF LINUX or MACOS or ANDROID}
{$IFDEF POSIX}
, reCodesetConversion
{$ENDIF POSIX}
, rePlatformNotImplemented, reObjectDisposed
);
如果您有真正的理由自己引发运行时错误,您可以通过调用来完成,例如:
System.Error(reZeroDivide);
如果你很细心,你会注意到 Error
在 System
单元中没有前向声明,而只存在于实现部分。通常,这会阻止您在其包含单元之外调用该方法的可见性,但 System
单元在许多方面都很特殊,并且此方法可在全球范围内访问。请注意,您还经常包含 Windows
单元,这声明了一个名为 ERROR
的常量,它通常会隐藏 System.Error
,因此通常需要显式限定它的范围。
当出现 EZeroDivide
、EOverflow
、EMathError
... 等异常时,它们会显示一条默认消息。
例如,以下代码引发 EZeroDivide
并显示以下消息:
Floating point division by zero
procedure TForm1.Button1Click(Sender: TObject);
var
N : Extended;
D : Extended;
begin
N := 100;
D := 0;
Caption := FloatToStr(N/D);
end;
当我 "manually" 通过代码引发 EZeroDivide
异常时,我必须将 Msg
参数传递给构造函数并将其作为 EZeroDivide
异常引发有一个空字符串消息:
procedure TForm1.Button2Click(Sender: TObject);
begin
raise EZeroDivide.Create('');
end;
默认异常消息从何而来?
那些异常实例是由 RTL 内部生成的。问题中的具体字符串可以在SysConst.pas
的resourcestring
部分找到
SZeroDivide = 'Floating point division by zero';
RTL 在内部使用 Error
方法来引发此类异常。运行时错误的完整列表在以下枚举的 System
单元中定义:
TRuntimeError = (reNone, reOutOfMemory, reInvalidPtr, reDivByZero,
reRangeError, reIntOverflow, reInvalidOp, reZeroDivide, reOverflow,
reUnderflow, reInvalidCast, reAccessViolation, rePrivInstruction,
reControlBreak, reWhosebug,
{ reVar* used in Variants.pas }
reVarTypeCast, reVarInvalidOp,
reVarDispatch, reVarArrayCreate, reVarNotArray, reVarArrayBounds,
reAssertionFailed,
reExternalException, { not used here; in SysUtils }
reIntfCastError, reSafeCallError,
reMonitorNotLocked, reNoMonitorSupport
{$IF defined(LINUX) or defined(MACOS) or defined(ANDROID)}
, reQuit
{$ENDIF LINUX or MACOS or ANDROID}
{$IFDEF POSIX}
, reCodesetConversion
{$ENDIF POSIX}
, rePlatformNotImplemented, reObjectDisposed
);
如果您有真正的理由自己引发运行时错误,您可以通过调用来完成,例如:
System.Error(reZeroDivide);
如果你很细心,你会注意到 Error
在 System
单元中没有前向声明,而只存在于实现部分。通常,这会阻止您在其包含单元之外调用该方法的可见性,但 System
单元在许多方面都很特殊,并且此方法可在全球范围内访问。请注意,您还经常包含 Windows
单元,这声明了一个名为 ERROR
的常量,它通常会隐藏 System.Error
,因此通常需要显式限定它的范围。