デバッガーとは何ですか?問題の診断にどのように役立ちますか?


107

これは、プログラムに問題があるが、デバッガーを使用して問題の原因を診断する方法がわからない新しいプログラマーを支援するための汎用的な質問を目的としています。

この質問は、より具体的な質問の3つのクラスをカバーしています。

  • プログラムを実行すると、指定した入力に対して期待する出力が生成されません。
  • プログラムを実行すると、プログラムがクラッシュし、スタックトレースが表示されます。スタックトレース調べましたが、スタックトレースで十分な情報が得られないため、問題の原因がわかりません。
  • プログラムを実行すると、セグメンテーション違反(SEGV)が原因でプログラムがクラッシュします。

3
ニースの仕事-また、関連を持っているためにQ&A「に行く」ために良いでしょう技術をデバッグする(例えばvalgrindの)、戦略的なprintfを、ストレステスト、分割統治、などなど、デバッガ、他のデバッグツールを使用して
ポールR

1
@PaulRに同意します。FAQにはこのようなものが含まれているはずです。
Nicu Stiurca 2014年

回答:


73

デバッガーは、プログラムの実行中にプログラムの状態を調べることができるプログラムです。それがこれを行うために使用する技術的手段は、デバッガを使用する方法の基本を理解するために重要ではありません。デバッガーを使用して、プログラムがコード内の特定の場所に到達したときにプログラムの実行を停止し、プログラム内の変数の値を調べることができます。デバッガーを使用して、変数の値を調べながら、一度に1行のコード(シングルステッピングと呼ばれる)でプログラムを非常にゆっくりと実行できます。

デバッガーの使用は、期待される基本的なスキルです

デバッガーは、プログラムの問題を診断するのに役立つ非常に強力なツールです。また、デバッガーはすべての実用的なプログラミング言語で利用できます。したがって、デバッガーを使用できることは、プロまたは熱狂的なプログラマーの基本的なスキルと見なされます。また、デバッガーを自分で使用することは、他の人に助けを求める前に自分で行う必要がある基本的な作業 と見なされます。このサイトは専門家や熱狂的なプログラマー向けであり、ヘルプデスクやメンタリングサイトではないため、特定のプログラムの問題について質問があるが、デバッガーを使用したことがない場合、質問は閉じられ、反対票を投じられる可能性が非常に高くなります。そのような質問を続けると、最終的にはそれ以上の投稿がブロックされます。

デバッガーがどのように役立つか

デバッガーを使用すると、変数の値が間違っているかどうか、およびプログラムのどこでその値が間違った値に変更されたかを検出できます。

シングルステッピングを使用すると、制御フローが期待どおりであるかどうかを確認することもできます。たとえば、ifブランチが実行されるはずのときに実行されるかどうかなどです。

デバッガーの使用に関する一般的な注意事項

デバッガーの使用の詳細は、デバッガーと、程度は低いものの、使用しているプログラミング言語によって異なります。

  • プログラムをすでに実行しているプロセスにデバッガーをアタッチできます。プログラムが動かなくなった場合は、そうするかもしれません。

  • 実際には、最初からデバッガーの制御下でプログラムを実行する方が簡単な場合がよくあります。

  • プログラムの実行を停止する場所を指定するには実行を停止する行のソースコードファイルと行番号を指定する、プログラムを停止するメソッド/関数の名前を指定します(として停止する場合)。実行がメソッドに入るとすぐに)。デバッガーがプログラムを停止させるために使用する技術的手段はブレークポイントと呼ばれ、このプロセスはブレークポイントの設定と呼ばれます

  • 最新のデバッガーのほとんどはIDEの一部であり、プログラムのソースコードと変数を調べるための便利なGUIと、ブレークポイントの設定、プログラムの実行、およびシングルステップ操作のためのポイントアンドクリックインターフェイスを提供します。

  • プログラムの実行可能ファイルまたはバイトコードファイルにデバッグシンボル情報とソースコードへの相互参照が含まれていない限り、デバッガーの使用は非常に難しい場合があります。あなたはする必要があるかもしれません若干異なるプログラムをコンパイル(または再コンパイル)の情報が存在することを確認するために。コンパイラが大規模な最適化を実行すると、これらの相互参照が混乱する可能性があります。したがって、最適化をオフにしてプログラム再コンパイルする必要がある場合があります


4
これは、Stackoverflowでの質問の数を大幅に減らす可能性のある最も重要なデバッガー(少なくとも20%予測)を見逃しているため、不完全です-javascriptデバッガー:firebug、Chrome、Firefox、IE9 +統合デバッガー、IE8- Visual Studioなど
slebetman 2014

1
node.jsの場合-ノードインスペクター。しかし、node.jsプログラマーは、一般的なjavascriptプログラマーほど多くの基本的な質問やfix-my-codeの質問をしません。
slebetman 2014

40

デバッガーが常に完璧なソリューションであるとは限らず、デバッグの頼りになるソリューションであるとは限らないことを付け加えたいと思います。デバッガーが機能しない場合がいくつかあります。

  • 失敗するプログラムの部分は非常に大きく(おそらくモジュール化が不十分ですか?)、コードのステップ実行をどこから開始すればよいか正確にはわかりません。すべてをステップスルーするのは時間がかかりすぎるかもしれません。
  • プログラムは多くのコールバックやその他の非線形フロー制御メソッドを使用しているため、ステップを実行するときにデバッガーが混乱します。
  • プログラムはマルチスレッドです。さらに悪いことに、問題は競合状態が原因です。
  • バグが含まれているコードは、バグが発生する前に何度も実行されます。これは、メインループで特に問題になる可能性があり、さらに悪いことに、問題が数値である可能性がある物理エンジンでは問題になる可能性があります。この場合、ブレークポイントを設定しても、バグが表示されずに何度もブレークポイントをヒットするだけです。
  • プログラムはリアルタイムで実行する必要があります。これは、ネットワークに接続するプログラムにとって大きな問題です。ネットワークコードにブレークポイントを設定した場合、もう一方の端はステップスルーを待つことはなく、単にタイムアウトになります。システムクロックに依存するプログラム、たとえばフレームスキップを使用するゲームも、それほど良いものではありません。
  • プログラムは、ファイルへの書き込みや電子メールの送信など、何らかの形の破壊的なアクションを実行しますが、実行する必要のある回数を制限したいと考えています。
  • バグの原因は関数Xに到達する誤った値であることがわかりますが、これらの値がどこから来ているのかはわかりません。プログラムを何度も何度も実行しなければならないこと、ブレークポイントをどんどん後ろに設定することは、非常に面倒なことです。特に関数Xがプログラム全体の多くの場所から呼び出された場合。

これらすべての場合において、プログラムを突然停止させると、最終結果が異なる可能性があります。または、バグが発生した1行を手動で検索するのは、非常に面倒です。これは、バグが正しくない動作であるか、クラッシュであるかにかかわらず、同様に発生する可能性があります。たとえば、メモリ破損によってクラッシュが発生した場合、クラッシュが発生するまでに、メモリ破損が最初に発生した場所から離れすぎており、有用な情報が残っていません。

それで、選択肢は何ですか?

最も単純なのは、単にロギングとアサーションです。さまざまな時点でプログラムにログを追加し、得られるものと期待するものを比較します。たとえば、バグがあると思われる関数が最初から呼び出されているかどうかを確認します。メソッドの開始時の変数があなたが思っているものであるかどうかを確認してください。ブレークポイントとは異なり、特別なことは何も起こらないログ行がたくさんあっても問題ありません。後でログを検索するだけです。予想とは異なるログ行に到達したら、同じ領域にさらに追加します。バグのある領域のすべての行をログに記録できるほど小さくなるまで、さらに絞り込みます。

アサーションは、エンドユーザーに表示される効果があった場合ではなく、発生したときに誤った値をトラップするために使用できます。間違った値をすばやくキャッチするほど、それを生成したラインに近づきます。

リファクタリングと単体テスト。プログラムが大きすぎる場合は、一度に1つのクラスまたは1つの関数をテストする価値があるかもしれません。入力を与え、出力を見て、どれが期待どおりでないかを確認します。プログラム全体から単一の関数にバグを絞り込むことができると、デバッグ時間に大きな違いが生じる可能性があります。

メモリリークやメモリ踏み込みが発生した場合は、実行時にこれらを分析および検出できる適切なツールを使用してください。実際の破損が発生した場所を検出できるようにすることが最初のステップです。この後、ログを使用して、誤った値が導入された場所に戻ることができます。

デバッグは逆行するプロセスであることを忘れないでください。最終結果(バグ)があり、それに先行する原因を見つけます。それはあなたのやり方を後退させることであり、残念ながら、デバッガーは前進するだけです。これは、優れたロギングと事後分析がはるかに優れた結果をもたらすことができる場所です。


10
これは良い答えになるでしょう...別の質問の。この質問に対する悪い答えです。おそらく、あなたはその質問をして、それに答えとしてこれを投稿するべきです。
レドワルド2015

9
実際の質問は、「プログラムに問題がある新しいプログラマーを支援する」、「期待する出力が生成されない」、「スタックトレースを調べたが、問題の原因がわからない」と説明されています。 。これらはすべて、この回答によって支援されています。さらに、デバッガーが何をするかを説明するときは、デバッガーが何をしないかを説明することも同様に重要です。
SlugFiller 2015

5
素晴らしい答え。私はいつもデバッガーをバグを見つけるためのメインツールとして使用していました。しかし今、私は巨大なインフラストラクチャコンポーネントが多くのスレッドと多くのネットワークコード(クライアント/サーバー)を使用しているプロジェクトで働いており、デバッガーが私を助ける最後のものであることに気づきました。古き良きデバッガー(最も重要なのはロギング)に頼るのではなく、実際には別のツールを使用する必要がある多くのことについて言及しました。
ティムシュメルター2017年

「バグの原因は関数Xに到達する誤った値であることがわかりますが、これらの値がどこから来ているのかわかりません」これは特にデバッグが困難です。通常、そのような問題をどのように修正しますか?
AyxanHaqverdili19年1

3
@Ayxanある程度、アサートで関数を中断させることができた場合は、呼び出しスタックを使用して呼び出し元を取得できます。ただし、値は前の行からのものである可能性が高いため、それだけでは値のソースは得られません。基本的に、値が通過するさまざまな変数を介して、値を追跡する必要があります。データがたどる経路をよく理解している場合は、一連のログプリントを作成し、「うまくいかない」場所を絞り込んでみてください。そうでない場合は、基本的に、ステップバックごとにプログラムを個別に実行する(エラーを再現する)必要があります。
SlugFiller
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.