13

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

Java では、スローできる例外を常に宣言する必要がありますが、Delphi ではそうではなく、未処理の例外が発生する可能性があります。

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

4

10 に答える 10

12

(編集:質問が設計時のチェックのみに言及していることは明らかです。)

新しい答え:

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

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

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

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

(前の回答: Application.OnException イベント ハンドラーを割り当てて、他の例外ハンドラーによって処理されないすべての例外をキャッチすることができます。これは実行時であり、したがって、おそらくあなたが求めているものとは正確には異なります (それはあなたがしたいように聞こえます)設計時にそれらを識別する)、他の場所で処理されない例外をトラップすることができます. Jedi Code Libraryの JCLDebug などのツールと組み合わせて、スタック トレースをログに記録し、例外が発生した場所と理由を見つけることができます。これにより、さらに調査し、有罪コードの周りに特定の例外処理または防止を追加できます... )

于 2008-09-16T14:22:27.873 に答える
11

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

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

于 2008-09-16T14:18:23.437 に答える
5

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

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

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

madExceptJclDebugEurekaLogなど、ランタイム例外の分析に役立つライブラリがいくつか存在します。これらのツールは、例外に関するあらゆる種類の詳細を記録できます。それらのいずれかを使用することを強くお勧めします!

于 2008-09-16T14:07:01.000 に答える
5

簡単に言えば、あなたの言うことを実行するツールはなく、raiseキーワードをスキャンしてもそこにたどり着けないということです。 EAccessViolationまたはEOutOfMemoryは、ほぼすべての場所で発生する可能性がある多数の例外のうちの 2 つにすぎません。

Delphi の基本的なことの 1 つは、例外が階層的であることです。定義されたすべての言語例外はExceptionから派生していますが、実際にはTObjectの子孫を発生させることが可能であることに注意してください。

特定の手順で発生したすべての例外をキャッチしたい場合は、それをtry / exceptブロックでラップするだけですが、前述のように、これはお勧めできません

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

それは、発生したTObjectのインスタンスであっても、すべてをキャッチします。これが最善の策であることはめったにないと私は主張しますが. 通常、try / finallyブロックを使用してから、グローバル例外ハンドラー (または 1 つの最後のtry / exceptブロック) が実際に例外を処理できるようにします。

于 2008-09-16T16:02:10.583 に答える
4

特定のレベルで明示的または一般的に処理されない例外は、コールスタックで上向きに細流化されます。Delphi RTL(ランタイムライブラリ)は、さまざまな例外クラスのセットを生成します-(数学エラー、アクセスエラー、クラス固有のエラーなど)。ブロックを除いて、具体的または一般的に別の試行でそれらを処理することを選択できます。

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

以前のコメント投稿者が書いたように、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;
于 2008-09-16T14:12:32.577 に答える
4

MadExceptを 2 番目 (または 3 番目)にします。いくつかの商用アプリケーションで問題なく使用できました。MadExcept の優れた点は、完全なスタック トレースを含むレポートを生成することです。これにより、通常、問題が発生した場合に正しい方向を示し、スクリーンショットを含めることもできます。これは自動的にメールで送信されます。単純なマウス クリックでクライアント コンピュータから。

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

于 2008-09-16T14:51:28.460 に答える
3

http://www.madshi.net/madExceptDescription.htmをご覧ください。

于 2008-09-16T14:03:33.550 に答える
1

Jim McKeeth が指摘しているように、決定的な答えを得ることはできませんが、特定の関数/手順が与えられた場合、コール グラフを構築するという静的分析によって、質問に部分的に答えることができるように思えます。そのコール グラフ内の各関数をチェックして、raise ステートメントを探します。たとえば、これは TIdTcpClient.ReadString が EIdNotConnected を発生させる可能性があることを示しています (とりわけ)。

巧妙なアナライザーは、一部のコードで / 演算子が使用され、可能性として EDivByZero が含まれていること、または一部のプロシージャが配列にアクセスして ERangeError が含まれていることに気付く場合もあります。

その答えは、単に「レイズ」を求めるよりも少しきついです。

于 2008-09-19T19:04:07.617 に答える
1

実行時はEurekalogを試してください。設計時にツールが存在するかどうかはわかりません。ソースのないサードパーティのコードがある場合でも、さらに困難が生じます。Delphi では例外をキャッチする必要がないため、Java のように例外を宣言する必要はありません。

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

于 2008-09-16T14:09:22.727 に答える