Откуда приходит сообщение об исключении? - PullRequest
0 голосов
/ 20 февраля 2019

Когда возникают исключения, такие как EZeroDivide, EOverflow, EMathError ..., они появляются с сообщением по умолчанию.

Например, следующий код вызывает EZeroDivide со следующимсообщение:

Деление с плавающей точкой на ноль

procedure TForm1.Button1Click(Sender: TObject);
var
  N : Extended;
  D : Extended;
begin
  N := 100;
  D := 0;
  Caption := FloatToStr(N/D);
end;

EZeroDivide Floating point division by zero

Когда я "вручную" поднимаюEZeroDivide исключение по коду, я должен передать параметр Msg в конструктор, и он вызывается как исключение EZeroDivide с пустым строковым сообщением:

procedure TForm1.Button2Click(Sender: TObject);
begin
  raise EZeroDivide.Create('');
end;

EZeroDivide without message

Откуда поступают сообщения об исключениях по умолчанию?

1 Ответ

0 голосов
/ 20 февраля 2019

Эти экземпляры исключений создаются внутри RTL.Конкретную строку в вопросе можно найти в разделе resourcestring файла SysConst.pas

 SZeroDivide = 'Floating point division by zero';

Внутренне RTL использует метод Error для вызова таких исключений.Полный список ошибок времени выполнения определен в блоке System в следующем перечислении:

TRuntimeError = (reNone, reOutOfMemory, reInvalidPtr, reDivByZero,
  reRangeError, reIntOverflow, reInvalidOp, reZeroDivide, reOverflow,
  reUnderflow, reInvalidCast, reAccessViolation, rePrivInstruction,
  reControlBreak, reStackOverflow,
  { 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, и это объявляет const с именем ERROR, который обычно скрывает System.Error, поэтому обычно требуется его явная область видимости.

...