Delphi 関数がスローする可能性のある例外を確認するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/72562

  •  09-06-2019
  •  | 
  •  

質問

Delphi でプロシージャ/関数 (プロシージャ/関数と呼ばれるものを含む) がどの例外を発生させるかを調べる良い方法はありますか?

Java では、どの例外をスローできるかを常に宣言する必要がありますが、Delphi ではそうではないため、ハンドルされない例外が発生する可能性があります。

未処理の例外を検出するコード分析ツールはありますか?

役に立ちましたか?

解決

(編集:質問が言及したものであることは明らかです のみ 設計時のチェックに使用されます。)

新しい答え:

これをチェックするツールがあるかどうかはわかりません。たとえば、Pascal Analyzer はそうではありません。

できる ただし、ほとんどの Delphi アプリケーションでは、これをチェックするツールがあったとしても、結果は得られません。

なぜ? TApplication.Run() のメイン メッセージ ループは、すべての HandleMessage() 呼び出しを例外処理ブロックにラップし、すべての例外タイプをキャッチするためです。したがって、ほとんどのアプリケーションでは、コードの約 99.999% で暗黙的/デフォルトの例外処理が行われます。そして、ほとんどのアプリケーションでは、この例外処理は独自のコードの約 100% になります。例外処理でラップされていないコードの 0.001% は、自動的に生成されたコードになります。

これをチェックできるツールがある場合は、例外処理が含まれないように Application.run() を書き直す必要があります。

(前の回答:Application.OnException イベント ハンドラーを割り当てると、他の例外ハンドラーでは処理されないすべての例外をキャッチできます。これは実行時であるため、正確にはあなたが望んでいることではないかもしれませんが (設計時にそれらを識別したいように思えます)、他の場所で処理されない例外をトラップすることができます。JCLDebug などのツールと併用すると、 ジェダイコードライブラリ, スタック トレースをログに記録して、例外が発生した場所と理由を調べることができます。これにより、さらなる調査が可能になり、有罪コードの周囲に特定の例外処理や防止を追加できます。)

他のヒント

私の推測では、Delphi を Java のように動作させようとしているのではないかと思いますが、これは良いアプローチではありません。未処理の例外についてはあまり心配しないことをお勧めします。最悪の場合、それらは汎用 VCL 例外ハンドラーにバブルアップし、Windows メッセージ ダイアログを引き起こします。通常のアプリケーションでは、アプリケーションが停止することはありません。

適切に記述されたコードは、発生する可能性のあるさまざまな例外を文書化し、意味のある方法で処理できるようにします。例外が発生した理由がわからない場合、実際に何をすべきかを知る方法がないため、キャッチオール ハンドラーは推奨されません。madExcept も強くお勧めします。

「raise」キーワードのスキャンを除いて、Delphi には、メソッドからどの例外が予想されるかを一般の読者に伝える言語構造はありません。

実行時に、すべてのメソッドにキャッチオール例外ハンドラーを追加することもできますが、実行速度が低下するため、それはお勧めできません。(そして、それを行うのも面倒です)。

メソッドに例外処理ブロックを追加すると、(例外がトリガーされない場合でも) いくつかのアセンブリ命令が追加され、メソッドが頻繁に呼び出される場合に測定可能な速度低下が生じます。

実行時例外の分析に役立つライブラリがいくつか存在します。 madExcept, Jclデバッグ, 、 そして エウレカログ. 。これらのツールは例外に関するあらゆる種類の詳細をログに記録できるため、これらのツールのいずれかを使用することを強くお勧めします。

簡単に言うと、あなたが言ったことを実行するツールはなく、 上げる キーワードではそこにたどり着けません。 Eアクセス違反 または Eメモリ不足 は、ほぼどこでも発生する可能性のある多数の例外のうちの 2 つにすぎません。

Delphi の基本的な点の 1 つは、例外が階層的であることです。定義されているすべての言語例外は以下から派生します。 例外, ただし、実際には任意の値を取得することが可能であることは注目に値します。 Tオブジェクト 子孫。

あなたがしたい場合は キャッチ 特定のプロシージャで発生するすべての例外を、 試してみます/除いて ブロックしますが、前述したように これはお勧めできません.

// Other code . . . 
try
  SomeProcedure()
except  // BAD IDEA!
  ShowMessage('I caught them all!');
end;

これにより、発生したインスタンスも含め、すべてがキャッチされます。 Tオブジェクト. 。ただし、これが最善の行動であることはめったにありません。通常、使用したいのは 試してみる/ついに ブロックしてから、グローバル例外ハンドラー (または最後の 1 つ) を許可します。 試してみます/除いて ブロック)を使用して実際に例外を処理します。

2番目にします(それとも3番目ですか) MadExcept. 。私はいくつかの商用アプリケーションで問題なく使用しています。MadExcept の優れた点は、何が問題になったのかについて正しい方向を示すフルスタック トレースを含むレポートを生成し、スクリーンショットも含めることができ、これが自動的に電子メールで送信されることです。クライアントコンピュータから簡単にマウスをクリックするだけでアクセスできます。

ただし、見逃した例外をキャッチするためだけに、すべての例外にこれを使用する必要はありません。たとえば、データベースを開いてログインが失敗した場合、アプリケーションで MadExcept のデフォルト エラーが発生したというメッセージをユーザーに表示するよりも、自分でこれをキャッチして処理する方が良いでしょう。

特定のレベルで明示的にまたは一般的に処理されない例外は、呼び出しスタック内で少しずつ上方に流れていきます。Delphi RTL (ランタイム ライブラリ) は、さまざまな例外クラスのセット (数学的エラー、アクセス エラー、クラス固有のエラーなど) を生成します。これらを別の tryException ブロックで具体的に処理するか、一般的に処理するかを選択できます。

例外を使用して特定の関数コンテキストを伝播する必要がない限り、新しい例外クラスを宣言する必要はありません。

以前のコメント投稿者が書いたように、MadExcept や EurekaLog などのすべての例外ハンドラーのマザーを追加して、キャッチされなかった例外をキャッチすることもできます。

編集:これは、未処理の例外に対する包括的な保険です。

try
  ThisFunctionMayFail;
except
  // but it sure won't crash the application
  on e:exception
  do begin
    // something sensible to handle the error 
    // or perhaps log and/or display the the generic e.description message
  end
end;

ランタイム用に試してみる エウレカログ. 。設計時にツールが存在するかどうかはわかりません。ソースのないサードパーティのコードを使用する場合でも、さらに困難が発生します。Delphi では例外をキャッチする必要がないため、Java のように例外を宣言する必要はありません。

私が言いたかったのは、Delphi では例外の処理が必要ないということです。プログラムが終了するだけです。EurekaLog は、処理された例外と未処理の例外をログに記録する手段を提供し、例外が発生したコード行や当時のコール スタックなど、例外が発生したときのプログラムの状態に関する豊富な情報を提供します。

ジム・マッキースが指摘しているように、決定的な答えは得られませんが、それは可能だと私には思えます。 部分的に 静的分析によって質問に答えます。特定の関数/プロシージャを指定して、コール グラフを構築します。その呼び出しグラフ内の各関数に raise ステートメントがあるかどうかを確認してください。これにより、たとえば、TIdTcpClient.ReadString が (とりわけ) EIdNotConnected を発生させる可能性があることがわかります。

賢いアナライザーは、一部のコードで / 演算子が使用され、可能性として EDivByZero が含まれていること、または一部のプロシージャが配列にアクセスし、ERangeError が含まれていることにも気づくかもしれません。

その答えは、単に「レイズ」を取得するよりも少し厳密です。

ユニットの終了セクションでも例外が発生する可能性があります。これらはすり抜けていくと思います...そして多少の問題もあります。

Delphi IDE には「スタック トレース」または「スタック ツリー」のようなものが組み込まれていると思います。

この質問を聞くと、Skybuck の TRussianRoulette ゲームを思い出します...グーグルで調べてください。コードと答えが役立つかもしれません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top