Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where does exception message comes from?

When exceptions like EZeroDivide, EOverflow, EMathError... are raised, they appear with a default message.

For example, the following code raises an EZeroDivide with the following message:

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;

EZeroDivide Floating point division by zero

When I "manually" raise an EZeroDivide exception by code, I have to pass the Msg parameter to the constructor and it is raised as an EZeroDivide exception which have an empty string message:

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

EZeroDivide without message

Where does default exception messages come from?

like image 484
Fabrizio Avatar asked Feb 20 '19 17:02

Fabrizio


People also ask

What does exception message mean?

Exception messages depend on the transaction being carried out and are meant to inform you of an important or critical event (for example, start date lies in the past, safety stock has been exceeded). By means of the exception messages, you can easily sort out any materials that you need to reprocess manually.

What causes an exception to be thrown?

An exception is thrown for one of three reasons: An abnormal execution condition was synchronously detected by the Java virtual machine. Such conditions arise because: evaluation of an expression violates the normal semantics of the language, such as an integer divide by zero, as summarized in §15.6.

What is the purpose of an exception?

Exceptions provide the means to separate the details of what to do when something out of the ordinary happens from the main logic of a program. In traditional programming, error detection, reporting, and handling often lead to confusing spaghetti code.

How can I get error message from exception object?

If you want the error class, error message, and stack trace, use sys. exc_info() . The function sys. exc_info() gives you details about the most recent exception.


1 Answers

Those exception instances are generated internally by the RTL. The specific string in the question can be found in the resourcestring section of SysConst.pas

 SZeroDivide = 'Floating point division by zero';

Internally the RTL uses the Error method to raise such exceptions. The full list of runtime errors is defined in the System unit in the following enum :

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
  );

If you have a genuine reason for raising a runtime error yourself you can do it by calling, for example :

 System.Error(reZeroDivide);

If you're very observant, you'll notice that Error does not have a forward declaration in the System unit but exists only in the implementation section. Typically this would prevent you from having visibility to call the method outside of its containing unit, but the System unit is special in many ways and this method is accessible globally. Just beware that you will also often be including the Windows unit and this declares a const named ERROR which will usually hide System.Error, so scoping it explicitly is usually required.

like image 99
J... Avatar answered Sep 20 '22 05:09

J...