Delphi Exception Handling in C++
Go Up to Exception Handling in C++Builder
C++Builder libraries may throw exceptions when something unexpected occurs. Since C++Builder libraries are written in Delphi, when you build C++ applications using C++Builder you need to understand how Delphi exception handling works, so that you can properly handle exceptions from libraries such as:
- The RTL
- FireMonkey
- VCL
Contents
Catching Delphi Exceptions
Exceptions from Delphi libraries must be caught by reference:
try {
// Code that uses Delphi libraries.
}
catch (ExceptionClass &E) {
// Handling of Delphi exceptions of type ExceptionClass.
}
For example, to catch an exception of class Exception and show its Message on a dialog box:
catch (Exception &E) {
ShowMessage(E.Message);
}
When catching exceptions from Delphi libraries:
- You cannot use throw to reraise Delphi exceptions that were caught unless you are in the catching stack frame.
- You are not responsible for freeing Delphi exception objects.
- You must explicitly catch exceptions from Delphi libraries in C++Builder graphical applications.
- Note: If you do not explicitly catch these exceptions, the default exception handler of the GUI framework of your application catches them, and your application raises an External Exception EEFFACE.
Delphi Constructors May Throw Exceptions
C++ destructors are called for members and base classes that are fully constructed.
Delphi base class destructors are called even if the object or base class is not fully constructed.
Object Destruction, Exceptions Thrown from Constructors provides an example that shows what happens if an exception is thrown during object construction.
Throwing Delphi Exceptions
You must throw instances of Delphi exception classes from C++ by value:
throw ExceptionClass();
For example, to throw an exception of class Exception and define an error Message:
throw Exception("My error message");
Common Delphi Exception Classes in C++Builder
C++Builder includes a large set of built-in exception classes for automatically handling divide-by-zero errors, file I/O errors, invalid typecasts, and many other exception conditions. To catch these exceptions, your application must link to the RTL. If your application does not link to the RTL, to handle this type of issues you should use signal-handling APIs of each operating system that your application supports, such as Structured Exception Handling on Windows.
In addition, Language Support for the RAD Studio Libraries (C++) describes subtle language differences that can cause exceptions.
Common RTL Exception Classes
RTL exceptions include access violations, integer math errors, floating-point math errors, stack overflow, and Ctrl+C interrupts.
Exception class | Description |
---|---|
EAbort | Stops a sequence of events without displaying an error message dialog box. |
EAccessViolation | Checks for invalid memory access errors. |
EBitsError | Prevents invalid attempts to access a Boolean array. |
EComponentError | Signals an invalid attempt to register or rename a component. |
EConvertError | Indicates string or object conversion errors. |
EDivByZero | Catches integer divide-by-zero errors. |
EExternalException | Signifies an unrecognized exception code. |
EInOutError | Represents a file I/O error. |
EIntOverflow | Specifies integer calculations whose results are too large for the allocated register. |
EInvalidArgument | Can be raised by some functions in the System.Math unit for out of range parameters. |
EInvalidCast | Checks for illegal typecasting. |
EInvalidOp | Invalid floating-point operation. For example, Floating-Point Exception: Stack Fault. |
EInvalidOperation | Occurs when invalid operations are attempted on a component. |
EInvalidPointer | Results from invalid pointer operations. |
EOleError | Specifies OLE automation errors. |
EOverflow | Floating-Point Exception: Divide by 0, Domain or Overflow |
EPropertyError | Occurs on unsuccessful attempts to set the value of a property. |
ERangeError | Indicates an integer value that is too large for the declared type to which it is assigned. |
ERegistryException | Specifies registry errors. |
System.SysUtils.EUnderflow | Floating-Point Exception: Partial Loss of Precision or Underflow |
EZeroDivide | Catches floating-point divide-by-zero errors. |
Common Data Access Exception Classes
Exception class | Description |
---|---|
EDatabaseError | Specifies a database access error. |
Common VCL Exception Classes
VCL exceptions:
Exception class | Description |
EDBEditError | Catches data incompatible with a specified mask. |
EInvalidGraphic | Indicates an attempt to work with an unrecognized graphic file format. |
EMenuError | Involves a problem with menu item. |
EOleCtrlError | Detects problems with linking to ActiveX controls. |
Custom Exception Classes that Descend from Delphi Classes
You can declare a new exception class by making it a descendant of class Exception and creating as many constructors as you need (or copy the constructors from an existing class in Sysutils.hpp
).
Portability considerations
Several runtime libraries (RTLs) are delivered with C++Builder. Most of them pertain to C++Builder applications, but one of them, cw32mt.lib, is the normal multi-threaded RTL that does not make any references to the VCL. This RTL is provided for support of legacy applications that may be part of a project but do not depend on the VCL. This RTL does not have support for catching operating system exceptions because those exception objects are derived from TObject and would require parts of the VCL to be linked into your application.
You can use the cp32mt.lib library, a multi-threaded runtime library, which provides memory management and exception handling with the VCL.
You can use two import libraries, cw32mti.lib and cp32mti.lib, for using the RTL DLL. Use cp32mti.lib for VCL exception support.