2

エラーメッセージなどを表示せずにアプリが消えてしまうバグがどこかにあります。アプリが画面から消え、タスク マネージャーに表示されなくなります。

このアプリは C++Builder アプリ (CBuilder2007) であり、このエラーをキャッチするために考えられるすべてのことを試しました。非常にめったに発生しません。私のマシンでは一度もクラッシュしたことがなく、オフィスにあるテスト マシンでは 1 回だけです。私たちの顧客の1人では、それがもう少し頻繁に発生しますが、それを実現する方法や、それが発生する状況を見つける方法が見つかりません. 重いマルチスレッドアプリです。

このアプリで madExcept を有効にしましたが、何もキャッチしません。set_terminateおよびset_unexpectedRTL ルーチンを使用してハンドラーを追加しましたが、うまくいきませんでした。

私が持っている唯一の情報は、メインアプリからリターンコードを取得するために行った「ローダーアプリ」ラッパーからのものです。コードで終了しC0000005ます。これは、アクセス違反が発生したことを意味すると思います。奇妙なことに、前述のように、Windows エラー ボックスなどもありません。

質問は次のとおりです。これをキャッチしようとするアイデアはありますか? これがどこで起こっているのか手がかりさえ持っていないので (私はアプリの周りにたくさんのログを記録していますが、アプリがクラッシュする前の「トレイル」はどこにもつながっていません)set_terminateset_unexpectedルーチンに関する私の考えは取得することでしたエラーが生成された場所を確認するためのスタック トレースですが、これまでのところ、これらのルーチンはまったく呼び出されていません (少なくとも、私のオフィスでこれが発生したのは 1 回だけです)。

前もって感謝します


[2009 年 9 月 22 日更新] AddVectoredHandlerException を使用して、クラッシュからコールスタックを取得できたので、バグの特定と修正を開始できます。ありがとう!!!

4

11 に答える 11

6

terminate/unexpectedは、C++ ランタイムによってのみ呼び出され、C++ 例外に対してのみ呼び出されます。

アクセス違反は SEH 例外です。これをキャッチするには、SetUnhandledExceptionFilterまたはAddVectoredExceptionHandler (>=XP の場合) が必要です。その後、 MiniDumpWriteDumpなどを使用してミニダンプを作成できます。

于 2009-09-19T19:48:04.563 に答える
3

アプリケーションが単に停止しているように見える、このような問題に数回遭遇しました。例外ハンドラやクラッシュ ハンドラなどは呼び出されません。アプリはすぐに終了するようです。

残念ながら、それを理解する方法について簡単なアドバイスを提供することはできません。ここでの他の回答には、いくつかの良いアイデアがあります。PiotrLegnica の応答に従って未処理の例外をキャッチするものがまだない場合は、そうする必要があります。

ただし、私がこれを見たときのように、プログラムが本当に即座に終了する場合は、登録されたハンドラーでさえSetUnhandledExceptionFilter役に立ちません。ハンドラが呼び出される前に、プログラムはすべての実行を停止し、メモリから削除されます。

ただし、いくつかのアイデアが思い浮かびます。

  • TerminateProcessまたはTerminateThreadの使用についてコードベースを確認してください。私は間違っているかもしれませんが、これらを使用すると、あなたが見ている症状を引き起こす可能性があると思います.
  • WindowProcWindow の API に渡されたコールバックや s など、関数ポインタの使用状況を確認します。呼び出し規則、パラメーター リスト、および戻り値がすべて正しく一致していることを確認してください。コードをコンパイルするために関数ポインターがキャストされている場合、悪いことが起こる原因となる不一致が隠されている可能性があります。
  • 使用しているサードパーティのライブラリまたはコンポーネント (ActiveX など) を検討してください。あいまいな状況でこの問題を引き起こす独自のコードにバグがある可能性があります。関数の呼び出しの前後にログ ステートメントを配置して、プログラムが停止する場所を特定できるかどうかを確認できます。
  • そして、他に何も役に立たない場合は、独自のコード全体にログを追加してください。

ロギングについて: 私の仕事で、このような問題を追跡するのを手伝わなければならなかったとき、プログラムが開始するたびに一意の名前のログを作成し、プログラムが終了するとそれを削除するロギング メカニズムを作成することになりました。通常は。そうすれば、終了の問題が発生するたびに別のログ ファイルが存在することになります。独自のネーミングの側面の一部として、日時スタンプを使用しました。ログの内容は、プログラムでどのアクションが発生したかの単なる記録です。ログを調査し、さらにログ ステートメントを追加することを何度か繰り返して、最終的にソースにたどり着きました。そして、問題を追跡している間、このメカニズムにより、問題がどのくらいの頻度で発生しているかについて非常に明確なアイデアが得られました. あなたは似たようなことを考えるかもしれません。

于 2009-09-19T23:35:42.170 に答える
1

再:アプリが消えます、顧客のマシンはWindowsで「エラーの報告」設定がオフになっていますか?これは「システム」コントロールパネルに埋め込まれており、オフにすると通常のWindowsクラッシュ通知ダイアログが表示されなくなります。

于 2009-09-19T20:14:46.890 に答える
1

ローカルで再現できないと大変なことになります。他の人が示唆しているように、クラッシュ ダンプを取得するか、デバッガーを使用して実行中のプログラムを取得することは、確かに最良の選択肢です。

これが私の問題なら、sysinternals の Process Monitor で監視してみます。プロセスのみを監視するように設定し、時間がかかる場合はファイルによってバックアップされていることを確認してください。これにより、アクティブなスレッドと、プロセスが終了したときに何が起こっているかがわかります。Windows の 'truss' に相当するもの (システム コールを監視するプログラム) を探すこともできます。

于 2009-09-21T15:00:46.847 に答える
1

たぶん、古き良きシグナルハンドラを追加することで、少なくとも何が起こったのかを示すことができるでしょうか?

于 2009-09-19T22:40:06.850 に答える
1

これが C++ コードで以前に 2 回発生するのを見たことがあります。

  1. Windows API を使用して動的にロードLoadLibraryGetProcAddress、間違った呼び出し規則で宣言された関数ポインターを介してそれを呼び出す場合 (それがあるべきでした__stdcallが、そうではありませんでした)。

  2. クラスがメンバ変数として関数ポインタを持っていて、関数ポインタが初期化される前に呼び出された場合。

于 2009-09-19T19:54:07.220 に答える
1

アプリケーションをデバッグ モードで実行し、一連の複雑なシナリオをどんどん実行してストレス テストを実行する必要があるため、デバッグ モードで例外をキャッチできます。

また、スレッド間の共有メモリへのアクセスを含むコードをもう一度確認してみてください。これはマルチスレッドの問題である可能性があります。すべての共有メモリ アクセスにロックを設定して、マルチスレッドが理由であることを確認できます (ただし、これによりパフォーマンスが低下します)。

于 2009-09-19T20:03:36.133 に答える
0

Windowsエラー報告を購読します。一部の顧客はAVをMicrosoftに報告し、Microsoftは収集されたスタックトレースを喜んで共有する可能性があります。利点として、アプリケーションの信頼性について確固たる数字を得ることができます。経営陣はそれらを愛しています。たとえば、「2010年までにエラーの頻度を50%削減する」という目標を設定できます。

于 2009-09-21T11:01:08.210 に答える
0

クラッシュの場合にミニダンプを書き込むようにアプリを構成します。

これが CBuilder でどのようになっているのかはわかりませんが、Visual Studio ではこのダンプを直接読み込むことができ、完全なコールスタックとクラッシュの原因となったソース コード行が表示されます。

お客様のマシンで発生したクラッシュの原因を見つけるために、これをよく使用しました。
ただし、特にマルチスレッド アプリケーションの場合は、実際のエラー (たとえば、メモリが早期に解放された) が実際のクラッシュの少し前に発生した可能性が高いため、根本的な原因を見つけることは依然として非常に困難な場合があります。

于 2009-09-19T20:03:17.373 に答える
0

過去にこれを実行したことがあると思われることが 2 つあります。それは、スタック オーバーフロー (無限再帰、大きな一時変数がスタックに配置される原因となる不適切なパラメーターなど)、またはセカンダリ スレッドでの未処理の例外です。

于 2009-09-19T19:57:57.133 に答える
0

アプリを実行してから、windbg (crash-mode) をアタッチして、2 回目の例外の最初の発生時にダンプが生成されるようにします。シンボル ファイル (PDB) を配置することを忘れないでください。

于 2009-09-21T11:27:41.940 に答える