5

奇妙に聞こえるかもしれませんが、多くのカスタム コンポーネントを含む大規模なアプリケーションで作業しているときに、誰もがこの種の問題に遭遇したと思います。AV はどこかで生成されますが、アプリケーションは実行を継続しており、後でエラーが発生します。マルチスレッドアプリケーションについて話しているのではありません。ほぼ一般的なシングル スレッド アプリケーションです。

ランダムに発生するエラーを見つけるのに苦労しています.MadExcept/AQTを使用してdcusとブレークポイントをデバッグしていますが、エラーが発生したときの正確な手順とどこから発生したかを見つけることができません. エラーが伝播しており、TWinControl destroy (Delphi 標準の TPageControl) で発生することもあれば、データセットを開くときに発生することもあります (同じ SQL で何度か開いて閉じる)。そのため、スタックが破損し、この場合は使用できません。

質問が局所的すぎることは承知していますが、そのような種類のエラーを追跡するために他にどのような方法があるかを尋ねています。

4

5 に答える 5

7

他のメモリ マネージャーを使用することから始めて、アプリケーションの使用パターンをより早く中断させることができるかどうかを確認します。

FastMMは FullDebugModeで実行できます (対応する DLL をアプリケーションの EXE に必ず配置してください)。それができるいくつかの重要なこと:

  • メモリをパターンで埋めます ( Arioch 'のように)
  • ブロックが解放された後、ブロックへの変更をチェックする
  • アプリケーション終了時のログ メモリ リーク
  • 特定のイベントでコールバックして、ログに記録できるようにします

過去に、FastMM について 2 つのブログ記事を書きましたが、FastMM とその他のメモリ マネージャーについてもっと書く必要があることはわかっています。

編集: SO ユーザーのEric Grangeによる、他のメモリ マネージャのMemory Manager Investigationsに関する素敵な記事。

ドキュメントの目的で、他のいくつかのメモリマネージャー (それらのほとんどはあなたのケースには当てはまりませんが、それらすべてを含む投稿をまだ見つけていません):

マルチスレッド環境では、次のようにすると便利です。

EXE/DLL のセットアップでは、FastShareMemを試してみてください。

André Mussche は彼のScaleMM リポジトリで、他のかなりの数のメモリ マネージャーをテストしました。

注意: +1; 良い質問です。Delphi メモリ マネージャーに関するフォローアップのブログ記事を書く時間を見つけてください(:

于 2013-06-18T13:12:37.687 に答える
3

ファイルにログを記録すると結果が変わる可能性があるため、出力ウィンドウにリアルタイムでメッセージを書き込む GExperts デバッガーをお勧めします。必要に応じてファイルにダンプしたり、ログに記録する内容を制御したり (ログレベル フィルター) したりできるように、ラッパー関数を記述します。

すべてのユニットの初期化/ファイナライズにロギングを入れます。ファイナライズ中に「思いがけない」エラーが頻繁に発生することがわかりました。例: データベース接続を閉じましたが、そのオブジェクトは他の何かによって既に解放されています。ああ!

また、コンポーネントのイベント ハンドラーと、それらのコンポーネントのデストラクタにログを記録します。これは、コンポーネントが破棄された後にイベントが発生しているかどうかを示します。

最後の手段として、「チャンク」で書いたすべてのコードを削除して、プログラムを「ガット」する必要がある場合があります。コードをどこかに保存し、form1 のイベント ハンドラーを削除し、コンパイルしてテストします。エラーが解消された場合は、イベント ハンドラーを元に戻し、半分を削除して、再テストします。十分に絞り込めるまで続けると、消去法により犯人が特定されるはずです。

于 2013-06-18T13:02:39.037 に答える
2

これは Delphi の質問よりも一般的な質問だと思います。ただし、次のような便利なテクニックがあります。

  • 後で調査できるように、ファイルへの過剰なログ記録 - すべての値を使用
  • どこでもアサーション。それらを無効にして、リリース時にコストを追加しないようにすることができます
  • エラーが表示されなくなるまでアプリケーションの一部を無効にする、または
  • 一部の基本的なシェルを除くすべてを無効にしてから、AV が戻るまでコンポーネントを 1 つずつ有効にします。
  • を使用したメモリ リークの追跡ReportMemoryLeaksOnShutdown := true

エラーを引き起こしていると思われるコンポーネントを見つけたら、そのコンポーネントに入り、その中のすべてを無効にし、パーツを段階的に有効にして手順を繰り返します。

于 2013-06-18T11:43:09.387 に答える
2

特に、Delphi だけでなく、非視覚的なものを開発するときは、次の 2 つのことが私の親友になりました。

  • 単体テストとロギング

(DUnit) は単体テストだけでなく、システム テストとストレス テストにも使用します。AQT を使用して、単体テストのカバレッジとメモリ リーク検出を評価しています。すべてのメソッドのテストを前もって書く必要はありませんが、できるだけ多くをカバーするテストを書くように努めます。特定の問題が発生した場合は、問題を再現するテストを作成し、修正がいつ機能するかを確認します。特に大きなアプリケーションでは、変更を行った後にテストを実行し、すべてが期待どおりに機能していることを確認できるという別の利点があります。

私が使用するもう 1 つのツールは SmartInspect です。これは、とりわけ、入退出方法をログに記録し、既存のコードをインストルメント化するためのウィザード (Enter Leave ログを追加する) と、ログをフィルター処理するためのコンソールを備えているためです。

于 2013-06-19T16:03:23.877 に答える