C++ での Delphi 例外処理
C++Builder の例外処理 への移動
C++Builder ライブラリでは、何か予期しないことが発生したときに例外を送出する可能性があります。C++Builder ライブラリは Delphi で記述されているため、C++Builder を使って C++ アプリケーションを作成する際には、下記などのライブラリから送出される例外を適切に処理できるように、Delphi 例外処理の動作の仕組みを理解しておく必要があります。
目次
Delphi 例外の捕捉
Delphi ライブラリから送出される例外は、次のように、参照で捕捉される必要があります。
try {
// Delphi ライブラリを使用しているコード
}
catch (ExceptionClass &E) {
// ExceptionClass 型の Delphi 例外の処理
}
たとえば、Exception クラス型の例外を捕捉し、そのメッセージ(Message プロパティ)をダイアログ ボックスに表示するには、次のようにします。
catch (Exception &E) {
ShowMessage(E.Message);
}
Delphi ライブラリから送出される例外を捕捉する場合は、次の点に注意してください。
- 例外を捕捉しているスタック フレームの中以外では、throw を使用して、捕捉した Delphi 例外を再発生させることはできません。
- Delphi 例外オブジェクトの解放は、プログラムで行うことではありません。
- C++Builder グラフィカル アプリケーションでは、Delphi ライブラリから送出される例外を明示的に捕捉する必要があります。
- メモ: これらの例外を明示的に捕捉しない場合は、アプリケーションの GUI フレームワークのデフォルト例外ハンドラでそれらが捕捉され、アプリケーションから外部例外 EEFFACE が発生します。
Delphi コンストラクタから送出される例外
C++ のデストラクタは、完全にインスタンスが生成されたメンバおよび基底クラスに対して呼び出されます。
Delphi の基底クラスのデストラクタは、オブジェクトや基底クラスのインスタンスが完全に生成されていない場合でも呼び出されます。
「オブジェクトの破棄」トピックの「コンストラクタから送出される例外」セクションには、オブジェクト生成中に例外が送出された場合どうなるかを示す例が掲載されています。
Delphi 例外の送出
C++ からは、次のように、Delphi 例外クラスのインスタンスを値で送出する必要があります。
throw ExceptionClass();
たとえば、エラー メッセージ(Message プロパティ)を指定して Exception クラスの例外を送出するには、次のようにします。
throw Exception("My error message");
C++Builder における一般的な Delphi 例外クラス
C++Builder には、ゼロ除算エラー、ファイル入出力エラー、無効な型キャストなど、さまざまな例外状況を自動的に処理するための多数の組み込み例外クラスが含まれています。これらの例外を捕捉するには、RTL をアプリケーションにリンクする必要があります。アプリケーションに RTL をリンクしない場合、この種の問題を処理するには、アプリケーションでサポートしている、各オペレーティング システムのシグナル処理 API(たとえば Windows の構造化例外処理など)を使用しなければなりません。
また、「RAD Studio ライブラリに対する言語サポート(C++)」では、例外の原因となり得る言語上の微妙な違いについて説明しています。
よく使用される RTL 例外クラス
RTL 例外には、アクセス違反、整数演算エラー、浮動小数点演算エラー、スタック オーバーフロー、Ctrl+C による割り込みなどがあります。
例外クラス | 説明 |
---|---|
EAbort | エラー メッセージ ダイアログ ボックスを表示せずに、一連のイベントを停止させます。 |
EAccessViolation | 不正なメモリ アクセスのエラーがないかどうかを確認します。 |
EBitsError | 論理型の配列に対する不正なアクセスを防止します。 |
EComponentError | コンポーネントの不正な登録や名前変更が試みられた場合に通知します。 |
EConvertError | 文字列やオブジェクトの変換エラーを示します。 |
EDivByZero | 整数のゼロ除算エラーを捕捉します。 |
EExternalException | 認識できない例外コードを通知します。 |
EInOutError | ファイル入出力エラーを表します。 |
EIntOverflow | 割り当てられたレジスタに対して整数計算の結果が大きすぎることを示します。 |
EInvalidCast | 不正な型キャストがないかどうかを確認します。 |
EInvalidOperation | コンポーネントに対して無効な操作が試みられたときに発生します。 |
EInvalidPointer | 無効なポインタ操作の結果として発生します。 |
EOleError | OLE オートメーション エラーを示します。 |
EPropertyError | プロパティの値を設定しようとして失敗した場合に発生します。 |
ERangeError | 整数値が割り当て先の宣言された型には大きすぎることを示します。 |
ERegistryException | レジストリ エラーを示します。 |
EZeroDivide | 浮動小数点数のゼロ除算エラーを捕捉します。 |
よく使用されるデータ アクセス例外クラス
例外クラス | 説明 |
---|---|
EDatabaseError | データベース アクセス エラーを示します。 |
よく使用される VCL 例外クラス
VCL 例外は次のとおりです。
例外クラス | 説明 |
EDBEditError | データが指定のマスクと互換性がない場合のエラーを捕捉します。 |
EInvalidGraphic | 認識できない形式のグラフィック ファイルが操作されようとしたことを示します。 |
EMenuError | メニュー項目に関する問題が関与していることを示します。 |
EOleCtrlError | Active X コントロールへのリンクに関する問題が検出されたことを示します。 |
Delphi クラスから派生するカスタム例外クラス
Exception クラスの下位クラスとして作成し、コンストラクタを必要なだけ作成(または Sysutils.hpp
に定義されている既存のクラスからコンストラクタをコピー)することにより、新しい例外クラスを宣言できます。
移植性に関する留意事項
C++Builder にはいくつかのランタイム ライブラリ(RTL)が付属しています。ほとんどは C++Builder アプリケーションに関するものですが、1 つだけ、cw32mt.lib は VCL をまったく参照しない通常のマルチスレッド対応 RTL です。この RTL は、プロジェクトの一部ではあるけれども VCL に依存していない既存アプリケーションをサポートするために用意されたものです。この RTL ではオペレーティング システム例外の捕捉をサポートしていません。というのも、これらの例外オブジェクトは TObject から派生しているため、アプリケーションにリンクするには VCL の一部が必要になるからです。
マルチスレッド対応ランタイム ライブラリの cp32mt.lib ライブラリを使用することができます。ここでは VCL によるメモリ管理と例外処理が提供されています。
RTL DLL を使用するには、cw32mti.lib および cp32mti.lib という 2 つのインポート ライブラリを使用できます。VCL 例外のサポートが必要であれば cp32mti.lib を使用してください。