Fixing defects in an engineered system
エンジニアリング において 、 デバッグとは バグの 根本原因 、 回避策 、および可能な修正方法 を見つけるプロセスです 。
ソフトウェア の場合、デバッグ手法には、 対話型 デバッグ、 制御フロー 解析、 ログファイル解析、 アプリケーション レベルまたは システム レベル での監視、 メモリダンプ 、 プロファイリング などが含まれます 。多くの プログラミング言語 や ソフトウェア開発ツールに は、デバッガーと呼ばれるデバッグを支援するプログラムも提供されています。
語源
マークIIのコンピュータログエントリ。ページに蛾が貼り付けられている。
欠陥という意味での「バグ 」という用語は 、少なくとも 1878 年にまで遡り、当時 トーマス・エジソンは 自身の発明における「小さな欠点や困難」を「バグ」と記していました。
1940年代によく知られた逸話の一つに、 グレース・ホッパー提督の 逸話があります。 [1]ハーバード大学で マークII コンピュータの開発に携わっていたとき 、同僚がリレーに 蛾 が挟まって動作を妨げているのを発見し、ログブックに「バグが発見された最初の実例」と記しました。これはおそらく「バグ」の二つの意味(生物学的な意味と欠陥の意味)を混同した ジョーク ですが、この逸話から、当時「バグ」という言葉がコンピュータ分野で使われていたことがわかります。
同様に、 「デバッグ」 という用語は、 コンピュータ の世界に入る前から航空学で使用されていました 。 第二次世界大戦中の 原子爆弾 マンハッタン計画 の責任者であったロスアラモス研究所の J・ロバート・オッペンハイマー は、 1944年10月27日付でカリフォルニア大学バークレー校の アーネスト・ローレンス 博士に 技術スタッフの追加募集に関する手紙の中で、「デバッグ」という用語を使用していました [2] 。 オックスフォード英語辞典の 「デバッグ」 の項目では、 1945年の王立航空学会誌の記事で、飛行機のエンジン試験に関して「 デバッグ 」という用語が使用されています 。また、「エアフォース」(1945年6月号、50ページ)の記事では、航空機のカメラの デバッグ について言及されています。
1951年にギル[3] が発表した画期的な論文は プログラミングエラーについて深く議論した最初の論文だが、 バグ や デバッグという 用語は使われていない。
ACM のデジタルライブラリ では、 デバッグ という用語は1952年のACM全国会議の3つの論文で初めて使用されています。 [4] [5] [6] 3つのうち2つでは、この用語が引用符で囲まれています。
1963年までに、 デバッグは CTSS マニュアルの1ページに説明なしにさらりと記載されるほど一般的な用語になりました 。 [7]
範囲
ソフトウェアや電子システムが一般的に複雑化するにつれ、様々な一般的なデバッグ手法が拡張され、異常の検出、影響度の評価、 ソフトウェアパッチ やシステム全体のアップデートのスケジュール設定など、より多くの手法が利用されるようになりました。「異常」や「不一致」という言葉は、 より中立的な用語 として、「エラー」や「欠陥」や「バグ」という言葉の使用を避けることができます。これらの言葉は、いわゆる エラー 、 欠陥 、 バグは すべて(どんな犠牲を払ってでも)修正しなければならないという含意を持つ可能性があります。代わりに、 影響評価を 行うことで、 異常 (または 不一致 )を除去するための変更がシステムにとって費用対効果が高いか、あるいは新しいリリースを予定することで変更が不要になるかどうかを判断できます。システムにおいて、すべての問題が 安全性 や ミッションクリティカルに 重要というわけではありません。また、変更が長期的にユーザーにとって、既知の問題を抱えたままでいるよりも大きな負担となるような状況(「治療が病気よりも悪い」状況)を避けることも重要です。一部の異常の許容可能性を基準に判断することで、「欠陥ゼロ」を強制する文化を避けることができます。この文化では、問題の存在を否定し、結果として 欠陥 ゼロに見えるようにしようとする誘惑に駆られる可能性があります。費用対効果の影響評価などの付随的な問題を考慮すると、より広範なデバッグ手法が拡張され、異常の発生頻度(同じ「バグ」がどのくらいの頻度で発生するか)を判定することで、システム全体への影響を評価するのに役立ちます。
ビデオゲーム コンソールのデバッグは、通常、開発者向けのこの Xbox デバッグ ユニットなどの特殊なハードウェアを使用して行われます。
デバッグの複雑さは、単純なエラーの修正から、データ収集、分析、更新スケジュールといった長くて面倒な作業まで、多岐にわたります。プログラマーのデバッグスキルは、問題のデバッグ能力を左右する重要な要素ですが、ソフトウェアデバッグの難易度はシステムの複雑さによって大きく異なり、使用する プログラミング言語 や デバッガー などの利用可能なツールにもある程度依存します。デバッガーは、プログラマーがプログラムの 実行を 監視し 、停止、再開、 ブレークポイントの 設定、メモリの値の変更などを行うことを可能にするソフトウェアツールです。 「 デバッガー」 という用語は、 デバッグを行う人を指す場合もあります。
一般的に、 Java などの 高水準プログラミング言語は、 例外処理 や 型チェック といった機能を備えているため、 異常な動作の真の原因を容易に特定できるため、デバッグが容易です。C言語 や アセンブリ言語などのプログラミング言語では、 バグによって メモリ破損 などの潜在的な問題が発生する場合があり 、最初の問題が発生した場所を特定するのが困難な場合がよくあります。そのような場合、 メモリデバッガ ツールが必要になることがあります。
特定の状況では、言語固有の性質を持つ汎用ソフトウェアツールが非常に役立つ場合があります。これらは 静的コード解析ツール の形をとります。これらのツールは、ソースコード内の非常に具体的な既知の問題(一般的なものから稀なものまで)を探し出し、コンパイラやインタープリタのように構文ではなく、セマンティクス(データフローなど)に重点を置いています。
様々な言語向けに、商用ツールと無料ツールの両方が存在し、中には数百もの異なる問題を検出できると主張するものもあります。これらのツールは、コードウォークスルーが現実的ではない、非常に大規模なソースツリーをチェックする際に非常に役立ちます。検出される問題の典型的な例としては、変数に値が代入される 前に 発生する変数の逆参照が挙げられます。また、一部のツールは、言語で必須ではない場合でも、強力な型チェックを実行します。そのため、構文的に正しいコード内のエラーの可能性の高い箇所を特定するのに優れています。しかし、これらのツールは、正しいコードを疑わしいコードとして検出してしまうという誤検知が多いという評判があります。古いUnixの lint プログラムは、その初期の例です。
電子ハードウェア(例: コンピュータハードウェア )だけでなく、低レベルソフトウェア(例: BIOS 、 デバイスドライバ )、 ファームウェアのデバッグには、 オシロスコープ 、 ロジックアナライザ 、 インサーキットエミュレータ (ICE)などの計測機器が単独または組み合わせて使用されることが多い。ICEは、低レベル ソフトウェア および ファームウェア に対して、典型的なソフトウェアデバッガのタスクの多くを実行できる 。
デバッグプロセス
デバッグプロセスは通常、問題を再現するための手順を特定することから始まります。これは、特に並列プロセスや一部の ハイゼンバグ などの場合、容易ではない作業となる場合があります。また、特定の ユーザー環境 や使用履歴によって、問題の再現が困難になる場合もあります。
バグが再現された後、デバッグを容易にするためにプログラムの入力を簡素化する必要がある場合があります。例えば、コンパイラのバグにより、大きなソースファイルを解析する際に クラッシュ が発生する可能性があります。しかし、テストケースを簡素化した後は、元のソースファイルの数行だけで同じクラッシュを再現できるようになります。簡素化は、 分割統治 法を用いて手動で行うことができます。この方法では、プログラマは元のテストケースの一部を削除し、それでも問題が発生するかどうかを確認します。GUI でデバッグする場合、プログラマは元の問題の説明からユーザーとのやり取りの一部を省略して 、 残りのアクションがバグの発生に十分かどうかを確認できます。
テストケースが十分に簡素化された後、プログラマーはデバッガーツールを使用してプログラムの状態(変数の値と コールスタック )を調べ、問題の原因を突き止めることができます。あるいは、 トレースを 使用することもできます。単純なケースでは、トレースはプログラム実行中の特定の時点での変数の値を出力するいくつかのprint文で済みます。 [ 要出典 ]
テクニック
対話型デバッグで は、デバッガ ツールを使ってプログラムの実行を 1 ステップずつ処理し、一時停止して状態を検査または変更できます。サブルーチンや関数呼び出しは通常、フル スピードで実行され、呼び出し元に戻った時点で再び一時停止するか、それ自体を 1 ステップ実行します。あるいは、これらのオプションを組み合わせたりすることもできます。セットポイントをインストールして、障害の疑いのないコードをフル スピードで実行し、障害のある時点で停止することもできます。プログラム ループの終了直後にセットポイントを配置すると、繰り返しコードを簡単に評価できます。特定の変数が変更されるまで実行を続行できるウォッチポイントや、例外や共有ライブラリの読み込みなどの特定の種類のプログラム イベントでデバッガを停止させるキャッチポイントも一般的に利用できます。
プリントデバッグ または トレースとは 、プロセスの実行フローとデータの進行を示すトレース文(プリント文)(ライブまたは記録)を監視する行為です。トレースは、専用のツール(GDBのトレースなど)を使用するか、ソースコードにトレース文を挿入することで実行できます。後者は、 printf デバッグは 、C言語のprintf の使用に由来します。 この種のデバッグは、初心者向け BASIC プログラミング言語のオリジナルバージョンでは、TRONコマンドによって有効化されていました。TRONは「Trace On」の略です。TRONは、プログラムの実行時に各BASICコマンドラインの行番号を表示します。
アクティビティ・トレースは 上記のトレースに似ていますが、プログラム実行を1命令または1関数ずつ追跡するのではなく、プロセッサ/CPUが特定のコードセグメントを実行するのに費やした総時間に基づいてプログラムアクティビティを追跡します。これは通常、定義されたメモリアドレス(マシンコードプログラム)または特定のプログラムモジュール(高級言語またはコンパイル済みプログラム)内の命令の処理に費やされたプログラム実行時間の割合として表示されます。デバッグ対象のプログラムがトレースされた領域内で実行時間の過度の割合を費やしていることが示された場合、これはプログラムロジックの欠陥によってプロセッサ時間の割り当てが誤っているか、少なくとも最適化の恩恵を受けるべきプロセッサ時間の割り当てが非効率的であることを示している可能性があります。
リモートデバッグ とは、デバッガとは異なるシステム上で実行されているプログラムをデバッグするプロセスです。リモートデバッグを開始するには、デバッガはローカルエリアネットワークなどの通信リンクを介してリモートシステムに接続します。デバッガはリモートシステム上のプログラムの実行を制御し、その状態に関する情報を取得できます。
事後デバッグと は、プログラムが クラッシュし た後にデバッグを行うことです。関連する技術としては、ログファイルの調査、 クラッシュ時の コールスタックの出力 [8] 、クラッシュしたプロセスの メモリダンプ (または コアダンプ )の分析など、様々なトレース技術 が含まれます。プロセスのダンプは、システムによって自動的に取得される場合(例えば、プロセスが未処理の例外によって終了した場合)、プログラマが挿入した命令によって取得される場合、あるいは対話型ユーザーによって手動で取得される場合があります。
「ウルフフェンス」アルゴリズム:エドワード・ガウスは、1982年に Communications of the ACM誌 に寄稿した記事の中で、このシンプルだが非常に有用で今では有名なアルゴリズムを 次のように説明している。「アラスカにはオオカミが1匹います。どうやって見つけますか?まず、州の真ん中にフェンスを作り、オオカミが遠吠えするのを待ち、フェンスのどちら側にオオカミがいるかを判断します。オオカミが見える地点に到達するまで、その側だけでこのプロセスを繰り返します。」 [9] これは、例えば Git バージョン管理システムでは git bisect コマンドとして実装されており、上記のアルゴリズムを使用してどの コミットが 特定のバグを引き起こしたか を判断します。
記録と再生によるデバッグは 、プログラム実行記録(例えば、Mozillaの無料デバッグツールrr を使用し、可逆的なデバッグ/実行を可能にする)を作成し、再生してインタラクティブにデバッグする手法です 。リモートデバッグや、断続的、非決定的、その他再現が難しい不具合のデバッグに役立ちます。
タイムトラベル デバッグ は、ソース コードを通じて時間を遡り ( Undo LiveRecorder を使用するなど)、コンピューター プログラムの実行中に何が起こっているかを把握し、ユーザーがプログラムを操作できるようにし、必要に応じて履歴を変更して、プログラムがどのように応答するかを確認するプロセスです。
デルタデバッグ – テストケースの簡素化を自動化する手法。 [10] : p.123
Saff Squeeze – 失敗したテストの一部を段階的にインライン化することで、テスト内の失敗を分離する手法。 [11] [12]
因果関係追跡 :計算における因果連鎖を追跡する技術があります。 [13] これらの技術は、ヌルポインタ参照などの特定のバグに合わせて調整できます。 [14]
自動バグ修正
組み込みシステムのデバッグ
汎用コンピュータソフトウェア設計環境とは対照的に、組み込み環境の主な特徴は、開発者が利用できるプラットフォーム(CPUアーキテクチャ、ベンダー、オペレーティングシステム、およびそのバリエーション)の多さです。組み込みシステムは、定義上、汎用設計ではありません。通常、単一のタスク(または限られた範囲のタスク)向けに開発され、プラットフォームはそのアプリケーションを最適化するために特別に選択されます。この事実は、組み込みシステム開発者の作業を困難にするだけでなく、プラットフォームごとに異なるデバッグツールが必要となるため、システムのデバッグとテストも困難にします。
上述の異種性の課題にもかかわらず、研究用プロトタイプだけでなく商用デバッガもいくつか開発されている。商用ソリューションの例としては 、 Green Hills Software [19] 、 Lauterbach GmbH [20] 、Microchip社のMPLAB-ICD(インサーキットデバッガ用)などがある。研究用プロトタイプツールの例としては、Aveksha [21] とFlocklab [22] がある。これらはすべて、低コストの組み込みプロセッサで利用可能な機能であるオンチップデバッグモジュール(OCDM)を活用しており、その信号は標準の JTAGインターフェース を介して公開される。これらは、アプリケーションに必要な変更の量と、対応できるイベントのレートに基づいてベンチマークされている。
組み込みシステムのデバッグでは、システム内のバグを特定するという一般的なタスクに加えて、システムの動作状態に関する情報も収集します。この情報は、システムの分析に使用でき、パフォーマンスを向上させる方法を見つけたり、その他の重要な特性 (エネルギー消費、信頼性、リアルタイム応答など) を最適化したりすることができます。
アンチデバッグ
アンチデバッグとは、「コンピュータコード内に、 対象プロセスの リバースエンジニアリングやデバッグを妨害する1つ以上の技術を実装すること」です。 [23]アンチデバッグは、著名な出版社による コピー防止 スキームにおいて積極的に利用されています が、 マルウェア によって検出と除去を困難にするためにも利用されています。 [24] アンチデバッグで使用される技術には、以下のものがあります。
APIベース: システム情報を使用してデバッガーの存在を確認する
例外ベース:例外が干渉されるかどうかを確認する
プロセスとスレッドブロック: プロセスとスレッドブロックが操作されたかどうかを確認します
変更されたコード: ソフトウェアブレークポイントを処理するデバッガによって行われたコードの変更をチェックします。
ハードウェアおよびレジスタベース: ハードウェアブレークポイントとCPUレジスタをチェックします
タイミングとレイテンシ:命令の実行にかかる時間をチェックする
デバッガーの検出とペナルティ [24]
アンチデバッグの初期の例としては、 Microsoft Word の初期のバージョンに存在していた。デバッガーが検出されると、「悪の木は苦い実を結びます。プログラムディスクを破棄します。」というメッセージが表示され、その後フロッピーディスクドライブから警告音が鳴り、ユーザーが再びデバッガーを操作しようとしないようにする意図があった。 [25] [26]
参照
参考文献
^ “InfoWorld Oct 5, 1981”. 1981年10月5日. 2019年9月18日時点のオリジナルよりアーカイブ。 2019年 7月17日 閲覧 。
^ “アーカイブコピー”. 2019年11月21日時点のオリジナルよりアーカイブ 。 2019年12月17日 閲覧。 {{cite web }}: CS1 maint: archived copy as title (link )
^ S. Gill, EDSACにおけるプログラムミスの診断(2020年3月6日アーカイブ、 Wayback Machine) , Proceedings of the Royal Society of London. Series A, Mathematical and Physical Sciences, Vol. 206, No. 1087 (May 22, 1951), pp. 538-554
^ Robert VD Campbell、「自動計算の進化」、 Wayback Machine で2019年9月18日にアーカイブ、1952年ACM全国会議(ピッツバーグ)の議事録、29-32ページ、1952年。
^ Alex Orden、「デジタルコンピュータによる線形不等式系の解法」、1952 ACM 全国会議 (ピッツバーグ) の議事録、p. 91-95、1952 年。
^ Howard B. Demuth、John B. Jackson、Edmund Klein、N. Metropolis、Walter Orvedahl、James H. Richardson、MANIAC doi=10.1145/800259.808982、1952年ACM全国会議(トロント)の議事録、p. 13-16
^ 互換タイムシェアリングシステム、 Wayback Machine で2012年5月27日にアーカイブ、MIT Press、1963年
^ 「Postmortem Debugging」. Dr. Dobb's . 2019年12月17日時点のオリジナルよりアーカイブ。 2019年12月17日 閲覧 。
^ EJ Gauss (1982). 「Pracniques: The 'Wolf Fence' Algorithm for Debugging」. Communications of the ACM . 25 (11): 780. doi : 10.1145/358690.358695 . S2CID 672811.
^ ゼラー、アンドレアス(2005年) 『なぜプログラムは失敗するのか:体系的デバッグガイド 』モーガン・カウフマン著、 ISBN 1-55860-866-4 。
^ 「Kent Beck, Hit 'em High, Hit 'em Low: Regression Testing and the Saff Squeeze」。2012年3月11日時点のオリジナルよりアーカイブ。
^ Rainsberger, JB (2022年3月28日). 「The Saff Squeeze」. The Code Whisperer . 2022年 3月28日 閲覧 。
^ Zeller, Andreas (2002-11-01). 「コンピュータプログラムから因果連鎖を分離する」. ACM SIGSOFT ソフトウェアエンジニアリングノート . 27 (6): 1– 10. doi :10.1145/605466.605468. ISSN 0163-5948. S2CID 12098165.
^ ボンド, マイケル・D.、ネザーコート, ニコラス、ケント, スティーブン・W.、ガイヤー, サミュエル・Z.、マッキンリー, キャサリン・S. (2007). 「Tracking bad apples」. 第22回ACM SIGPLANオブジェクト指向プログラミングシステムおよびアプリケーション会議 - OOPSLA '07 議事録 . p. 405. doi :10.1145/1297027.1297057. ISBN 9781595937865 . S2CID 2832749。
^ Rinard, Martin C. (2008). 「技術的視点から見たプログラムエラーの パッチ適用 」 Communications of the ACM . 51 (12): 86. doi :10.1145/1409360.1409381. S2CID 28629846.
^ Harman, Mark (2010). 「自動パッチ適用技術」 Communications of the ACM . 53 (5): 108. doi :10.1145/1735223.1735248. S2CID 9729944.
^ ab Gazzola, Luca; Micucci, Daniela; Mariani, Leonardo (2019). 「自動ソフトウェア修復:概要」 (PDF) . IEEE Transactions on Software Engineering . 45 (1): 34– 67. doi : 10.1109/TSE.2017.2755013 . hdl :10281/184798. S2CID 57764123.
^ Tan, Shin Hwei; Roychoudhury, Abhik (2015). 「relifix: ソフトウェア回帰の自動修復」 2015 IEEE/ACM 第37回IEEE国際ソフトウェア工学会議 IEEE. pp. 471– 482. doi :10.1109/ICSE.2015.65. ISBN 978-1-4799-1934-5 . S2CID 17125466。
^ 「SuperTrace Probe ハードウェアデバッガー」 www.ghs.com 。2017年12月1日時点のオリジナルよりアーカイブ 。 2017年11月25日 閲覧。
^ 「デバッガーとリアルタイムトレースツール」 www.lauterbach.com . 2022年1月25日時点のオリジナルよりアーカイブ 。 2020年6月5日 閲覧。
^ Tancreti, Matthew; Hossain, Mohammad Sajjad; Bagchi, Saurabh; Raghunathan, Vijay (2011). 「Aveksha」. 第9回ACM組み込みネットワークセンサーシステム会議論文集 . SenSys '11. ニューヨーク、ニューヨーク州、米国: ACM. pp. 288– 301. doi :10.1145/2070942.2070972. ISBN 9781450307185 . S2CID 14769602。
^ Lim, Roman; Ferrari, Federico; Zimmerling, Marco; Walser, Christoph; Sommer, Philipp; Beutel, Jan (2013). 「FlockLab」. 第12回国際センサーネットワーク情報処理会議議事録 . IPSN '13. ニューヨーク、ニューヨーク州、米国: ACM. pp. 153– 166. doi :10.1145/2461381.2461402. ISBN 9781450319591 . S2CID 447045。
^ Shields, Tyler (2008年12月2日). 「Anti-Debugging Series – Part I」. Veracode . 2016年10月19日時点のオリジナルよりアーカイブ 。 2009年3月17日 閲覧。
^ ab 「アンチデバッグによるソフトウェア保護:Michael N Gagnon、Stephen Taylor、Anup Ghosh」 (PDF) 。 2011年10月1日時点の オリジナル (PDF)からアーカイブ。 2010年10月25日 閲覧 。
^ Ross J. Anderson (2001-03-23). セキュリティエンジニアリング . Wiley. p. 684. ISBN 0-471-38922-6 。
^ “Microsoft Word for DOS 1.15”. 2013年5月14日時点のオリジナルよりアーカイブ 。 2013年6月22日 閲覧。
さらに読む
外部リンク
Wikiquote には、デバッグ に関する引用があります 。
ウィキブックの 「コンピュータプログラミングの原則」には、 デバッグ に関するページがあります。
クラッシュダンプの分析パターン - クラッシュダンプのバグの分析と発見に関する詳細な記事
デバッグの基本 – デバッグスキルを向上させる方法
組み込みシステム向けプラグインベースのデバッグ
組み込みシステムのテストとデバッグ - デジタル入力生成について - 組み込みシステムのテストとデバッグに関する調査結果、Byte Paradigm(2012年1月12日アーカイブ)