
ソフトウェアバグとは、コンピュータソフトウェアの欠陥(バグ)のことです。バグが多い、あるいは深刻なバグのあるコンピュータプログラムは、「バグだらけ」と表現されることがあります。
ソフトウェアのバグの影響は、軽微なもの(ユーザーインターフェースのスペルミスなど)から深刻なもの(頻繁なクラッシュなど)まで多岐にわたります。
2002年、米国商務省国立標準技術研究所が委託した調査では、「ソフトウェアのバグ、つまりエラーは非常に蔓延しており、非常に有害であるため、米国経済に 年間推定590億ドル、つまり国内総生産の約0.6%の損失を与えている」と結論付けられた。 [ 1 ]
1950年代以降、一部のコンピュータシステムは、動作中に様々なソフトウェアエラーを検出したり、自動的に修正したりするように設計されてきた。
欠陥を表す「バグ」という用語は、電子計算機やコンピュータソフトウェアが登場するずっと前の1870年代から、少なくとも工学用語として使われてきました。例えば、トーマス・エジソンは1878年に同僚に宛てた手紙の中で、次のように書いています。
私の発明はすべてそうでした。最初のステップは直感で、閃きとともに訪れますが、その後困難が生じます。この製品は機能しなくなり、そこで「バグ」と呼ばれる小さな欠陥や問題が現れ、商業的な成功または失敗が確実に訪れるまでには、数ヶ月にわたる集中的な観察、研究、作業が必要になります。[ 2 ]
第二次世界大戦中の軍事装備の不具合は、バグまたはグリッチと呼ばれていた。[ 3 ]
アイザック・アシモフは、 1944年に発表された短編小説「ウサギを捕まえろ」の中で、ロボットの不具合を表すのに「バグ」という言葉を使った。

コンピューターのパイオニアであるアメリカ海軍少将グレース・ホッパーは、初期の電気機械式コンピューターで蛾が問題を引き起こしたという話を広めた。[ 4 ]ホッパーが1947年頃、ハーバード大学の教員としてMark IIとMark IIIに取り組んでいたとき、オペレーターはMark IIのエラーの原因がリレーに挟まった蛾であることを突き止めた。蛾は機構から取り除かれ、「バグが発見された最初の実際の事例」というメモとともにログブックにテープで貼り付けられた。 [ 5 ]伝えられるところによると、後にバージニア州ダールグレンの海軍兵器研究所に所属することになる ウィリアム「ビル」バークを含むオペレーターたちは、工学用語に精通しており、おそらくバグの2つの意味(生物学的バグと技術的バグ)を混同して駄洒落を言っていたのだろう。冗談だったとしても、この話は当時コンピューター分野でこの用語が一般的に使われていたことを示している。[ 7 ] [ 8 ] [ 9 ] [ 10 ]
ミスの変容(ギリシャ語のmeta = "変化"、morph = "形" に由来)とは、ソフトウェア展開の最終段階における欠陥の進化を指します。ソフトウェア開発ライフサイクルの初期段階でアナリストが犯したミスが、サイクルの最終段階で欠陥につながる変容は、ミスの変容と呼ばれています。[ 11 ]
開発サイクルにおけるミスのさまざまな段階は、ミス、[ 12 ] : 31異常、[ 12 ] : 10障害、[ 12 ] : 31失敗、[ 12 ] : 31エラー、[ 12 ] : 31例外、[ 12 ] : 31クラッシュ、[ 12 ] : 22グリッチ、バグ、[ 12 ] : 14欠陥、インシデント、[ 12 ] : 39または副作用として説明できます。
ソフトウェアのバグは災害と関連付けられている。
ソフトウェアの動作を説明する際に「バグ」という言葉を使うことは、認識の違いから議論の的になることがある。バグという言葉は欠陥が自然に発生したことを示唆するとして、この用語の使用をやめるべきだと主張する人もいる。代わりに「欠陥」という言葉を使うべきだという意見もある。欠陥という言葉の方が、人間が原因であることをより明確に示しているからだ。[ 17 ]
バグは意図的な設計上の決定を隠蔽するために使われている可能性があると主張する人もいる。2011年、ユーザーの位置情報を暗号化されていないファイルに記録して保存していることで米国のアル・フランケン上院議員から批判を受けた後、 [ 18 ] Appleはこの動作をバグと呼んだ。しかし、民主主義とテクノロジーセンターのジャスティン・ブルックマンはこの説明に直接異議を唱え、「彼らがバグと呼ぶものを修正しているのは喜ばしいが、ユーザーを追跡していることを強く否定している点には異議がある」と述べた。[ 19 ]

ソフトウェア開発プロセスのできるだけ早い段階でバグを防止することは、投資とイノベーションの目標である。[ 20 ] [ 21 ]
新しいプログラミング言語は、既存の言語の脆弱性に基づく一般的なバグを防止するように設計される傾向があります。BASICやCなどの古い言語から得られた教訓は、C #やRustなどの後発の言語の設計に役立てられています。
コンパイル言語では、実行時前に(例えば、識別子のスペルミスなど)いくつかのタイプミスを検出できるため、インタプリタ言語よりもソフトウェア開発プロセスの早い段階で検出が可能になります。
言語には、静的型システム、制限された名前空間、モジュール型プログラミングなどの機能が含まれる場合があります。たとえば、型付きコンパイル言語(C言語など)の場合:
float num = "3";
構文的には正しいが、右辺が文字列であるため、float型の変数に代入できず、型チェックに失敗する。コンパイルエラーが発生するため、開発を再開するにはこの欠陥を修正する必要がある。インタプリタ型言語の場合、このエラーはステートメントが実行されるまで(実行時であればずっと後)発生しない。
一部のプログラミング言語は、バグが発生しやすい機能をあえて排除することで、パフォーマンスの低下を招いています。これは、複雑でバグの多いコードを書くよりも、シンプルで遅くても正しいコードを書く方が一般的に優れているという考えに基づいています。例えば、Javaはポインタ演算をサポートしていません。ポインタ演算は非常に高速ですが、慎重に使用しないとメモリ破損やセグメンテーション違反を引き起こす可能性があります。
一部のプログラミング言語には、一般的なバグを防ぐために実行時オーバーヘッドを追加する機能が含まれています。例えば、多くの言語には実行時境界チェック機能や、境界外エラーが発生した場合にクラッシュするのではなく回復する仕組みが備わっています。
スタイルガイドラインと防御的なプログラミングによって、見落としやすいタイプミス(誤植)を防ぐことができます。
例えば、ほとんどのC系プログラミング言語では、命令が1つしかない場合、命令ブロックを囲む中括弧を省略できます。次のコードは、条件が真のfoo場合にのみ関数を実行しますcondition。
条件が満たされた場合 foo();
しかし、このコードは常に実行されますfoo。
条件を満たす場合 foo();
括弧を使用することは、厳密には必須ではない場合でも、このエラーを確実に防ぎます。
if (条件) { foo(); }規約の遵守は、手動(コードレビューなど)で行うことも、リンターなどの自動ツールで行うこともできます。
プログラムの意図する動作を記述したプログラム仕様書を作成することで、バグを防ぐことができると主張する人もいる。しかし、組み合わせ爆発や不確定性の問題があるため、形式仕様書は最短のプログラム以外には実用的ではないと主張する人もいる。
ソフトウェアテストの目的の一つはバグを見つけることです。テスト中の測定によって、残っている可能性のあるバグの数を推定できます。製品のテストと開発期間が長くなるほど、この推定の信頼性は高まります。[ 22 ]
アジャイルソフトウェア開発では、比較的小規模な変更を頻繁に行うソフトウェアリリースが一般的です。欠陥はユーザーからのフィードバックによって明らかになります。
テスト駆動開発(TDD)では、本番コードを作成する際に同時に単体テストも作成され、すべてのテストが作成され、正常に完了するまで本番コードは完成したとはみなされません。
静的コード解析ツールは、コンパイラの能力を超えてプログラムテキストを検査し、潜在的な問題を特定することで、開発者を支援します。一般的に、仕様に基づいてすべてのプログラミングエラーを見つけるという問題は解決不可能ですが(停止問題を参照)、これらのツールは、人間のプログラマーがソフトウェアを作成する際に特定の種類の単純なミスを犯しやすいという事実を利用しています。
ソフトウェアの実行中にパフォーマンスを監視するツールは、ボトルネックなどの問題を特定したり、正しく動作していることを確認したりするために、コードに明示的に組み込むことも(例えば、単に `.` という文を記述するだけで済む場合もあるPRINT "I AM HERE")、ツールとして提供することもできます。処理時間の大部分が特定のコードによって費やされていることに気づいて驚くこともよくあり、こうした前提を取り除くことで、コードの書き直しが必要になる場合もあります。
Open source development allows anyone to examine source code. A school of thought popularized by Eric S. Raymond as Linus's law says that popular open-source software has more chance of having few or no bugs than other software, because "given enough eyeballs, all bugs are shallow".[23] This assertion has been disputed, however: computer security specialist Elias Levy wrote that "it is easy to hide vulnerabilities in complex, little understood, and undocumented source code," because, "even if people are reviewing the code, that doesn't mean they're qualified to do so."[24] An example of an open-source software bug was the 2008 OpenSSL vulnerability in Debian.
Debugging can be a significant part of the software development lifecycle. Maurice Wilkes, an early computing pioneer, described his realization in the late 1940s that "a good part of the remainder of my life was going to be spent in finding errors in my own programs".[25]
Typically, the first step in locating a bug is to reproduce it reliably. If unable to reproduce the issue, a programmer cannot find the cause of the bug and therefore cannot fix it.
Some bugs are revealed by inputs that may be difficult to reproduce. One cause of the Therac-25 radiation machine deaths was a bug (specifically, a race condition) that occurred only when the machine operator very rapidly entered a treatment plan; it took days of practice to become able to do this, so the bug did not manifest in testing or when the manufacturer attempted to reproduce it. Other bugs may stop occurring whenever the setup is augmented to help find the bug, such as running the program with a debugger; these are called heisenbugs (humorously named after the Heisenberg uncertainty principle).
Sometimes, a bug is not an isolated flaw, but represents an error of thinking or planning on the part of the programmers. Often, such a logic error requires a section of the program to be overhauled or rewritten. a process known as code refactoring.
A code review, stepping through the code, and imagining or transcribing the execution process, may often find errors without ever reproducing the bug as such.
A program known as a debugger can help a programmer find faulty code by examining the inner workings of a program, such as executing code line-by-line and viewing variable values.
デバッガーを使用する代わりに、プログラムの実行を追跡し、値を表示するためにデバッグ情報を出力するロジックをコードに組み込むことができます。出力は通常、コンソール、ウィンドウ、ログファイル、またはハードウェア出力(場合によってはインジケータLEDを駆動する)に行われます。
1990年代以降、特にアリアン5 501便の事故以降、抽象解釈による静的コード解析などのデバッグの自動化支援への関心が高まった。[ 26 ]
組み込みシステムでは、ハードウェアのバグを回避するためにソフトウェアを修正することがよくあります。これは、ソフトウェアの修正の方がハードウェアの修正よりも安価で、システムへの影響も少ないためです。

バグは、文書化、分類、担当者の割り当て、再現、修正、修正済みコードのリリースといった活動を通じて管理されます。
ソフトウェアのバグやその他の問題を追跡するためにツールがよく使用されます。通常、ソフトウェア開発チームが作業負荷を追跡するために使用するツールと、カスタマーサービスがユーザーからのフィードバックを追跡するために使用するツールは異なります。[ 27 ]
追跡対象項目は、バグ、欠陥、チケット、課題、機能などと呼ばれることが多く、アジャイルソフトウェア開発ではストーリーやエピックと呼ばれることもあります。項目は、深刻度、優先度、影響を受けるバージョン番号などの側面によって分類されることがよくあります。
トリアージと呼ばれることもあるプロセスでは、バグの深刻度や優先度、開発スケジュールなどの外部要因などの情報に基づいて、各バグを修正するかどうか、いつ修正するかが決定されます。トリアージには通常、原因の調査は含まれません。トリアージは定期的に行われる場合があり、少なくとも前回のトリアージ以降に発生した新しいバグのレビューから始まり、場合によってはすべての未解決のバグにまで及ぶ可能性があります。参加者には、プロジェクト マネージャー、開発マネージャー、テスト マネージャー、ビルド マネージャー、および技術専門家が含まれる場合があります。[ 28 ] [ 29 ]
深刻度は、バグがもたらす影響の尺度です。[ 30 ]この影響には、データ損失、金銭的損失、信用の喪失、無駄な労力などが含まれます。深刻度レベルは標準化されておらず、業界や追跡ツールなどのコンテキストによって異なります。たとえば、ビデオゲームのクラッシュは、銀行サーバーのクラッシュとは異なる影響をもたらします。深刻度レベルの説明の例としては、クラッシュまたはハング、回避策なし(ユーザーはタスクを完了できない)、回避策あり(ユーザーはタスクを完了できる)、視覚的欠陥(たとえばスペルミス)、ドキュメントエラーなどがあります。深刻度の別の例としては、重大、高、低、ブロッカー、些細などがあります。[ 31 ]バグの深刻度は、修正の優先度と同じカテゴリである場合もあれば、2つを別々に定量化して管理する場合もあります。
優先度とは、他のバグとの関連において、そのバグを解決することの重要性を表すものです。優先度は、1から5などの数値で表される場合もあれば、重大、高、低、延期といった名称で表される場合もあります。優先度は異なる側面ではありますが、その値は深刻度評価と類似または同一である可能性があります。
優先度は、バグの深刻度と修正に必要な労力の組み合わせによって決まる場合があります。深刻度は低いものの修正が容易なバグは、深刻度が中程度でも修正にかなりの労力を要するバグよりも優先度が高くなる可能性があります。
優先度の高いバグは、それを修正するための特別なリリースが必要となる場合があります。このようなリリースは、パッチと呼ばれることもあります。
バグ修正を重視したソフトウェアリリースは、新機能やその他の変更を重視したリリースと区別するために、メンテナンスリリースと呼ばれることがある。
既知の低優先度バグやその他の問題を抱えたままソフトウェアをリリースすることはよくあることです。考えられる理由としては、以下のようなものが挙げられますが、これらに限定されるものではありません。
ソフトウェアのバグが引き起こす損害の量と種類は、ソフトウェアの品質に関する意思決定、プロセス、およびポリシーに影響を与えます。有人宇宙飛行、航空、原子力発電、医療、公共交通機関、自動車安全などの分野では、ソフトウェアの欠陥が人身傷害や死亡事故につながる可能性があるため、例えばオンラインショッピングサイトなどと比べて、はるかに厳格な検査と品質管理が行われます。銀行業務のように、ソフトウェアの欠陥が銀行や顧客に深刻な金銭的損害を与える可能性がある分野でも、例えば写真編集アプリケーションなどと比べて、品質管理はより重要になります。
バグによる損害以外にも、バグの修正に費やされる労力がコストの一部を占めています。1978年にLientzらは、プロジェクトの平均が開発労力の17%をバグ修正に費やしていることを示しました。[ 36 ] 2020年のGitHubリポジトリに関する調査では、平均が20%であることが示されました。[ 37 ]
1994年、NASAのゴダード宇宙飛行センターは、平均エラー数を1,000行のコード( SLOC )あたり4.5件から1件に削減することに成功した。[ 38 ]
1990年の別の研究では、非常に優れたソフトウェア開発プロセスでは、 1000 SLOC あたり 0.1 という低い展開失敗率を達成できることが報告されています。[ 39 ]この数値は、 Steve McConnellのCode Complete [ 40 ]やNASA の Flight Software Complexity に関する研究[ 41 ]などの文献で繰り返し言及されています。一部のプロジェクトでは、欠陥ゼロを達成したものもあります。IBM Wheelwriterタイプライターのファームウェア(63,000 SLOC) や、スペースシャトルのソフトウェア (500,000 SLOC) などです。[ 39 ]
テストとデバッグに関する再現可能な研究を促進するために、研究者は厳選されたバグのベンチマークを使用します。
注目すべきバグの種類:
バグは、仕様に基づいた設計が不十分または不正確であることに起因する場合があります。例えば、仕様が単語リストをアルファベット順に並べることである場合、設計で記号が考慮されていないと、記号を含む単語が正しくアルファベット順に並べられないという設計上のバグが発生する可能性があります。
数値演算は、予期しない出力、処理の遅延、またはクラッシュを引き起こす可能性があります。[ 46 ]このようなバグは、丸めによる精度の低下、数値的に不安定なアルゴリズム、算術オーバーフローやアンダーフローなどのデータストレージの特性に対する 認識不足、または、ゼロ除算など、さまざまなソフトウェアコーディング言語による計算の処理方法に関する認識不足から発生する可能性があります。ゼロ除算は、一部の言語では例外をスローし、他の言語ではNaNや無限大などの特殊な値を返す場合があります。
制御フローのバグ、または論理エラーは、エラーで失敗しないものの、無限ループ、無限再帰、条件式における誤った比較(誤った比較演算子の使用など)、オフバイワンエラーなど、期待される動作をしないコードによって特徴付けられます。
ニュー・アメリカという団体が運営するオープン・テクノロジー・インスティテュート[51]は、2016年8月に「システムのバグ」という報告書を発表し、米国の政策立案者は研究者がソフトウェアのバグを特定して対処できるよう改革を行うべきだと述べた。この報告書は「ソフトウェアの脆弱性の発見と開示の分野における改革の必要性を強調している」[ 52 ] 。報告書の著者の1人は、議会はサイバーセキュリティというより大きな問題に対処するために多くの法案を可決したが、サイバーソフトウェアの脆弱性に対処するには十分なことをしていないと述べた[ 52 ] 。
政府の研究者、企業、サイバーセキュリティの専門家が、通常ソフトウェアの欠陥を発見する人々である。報告書は、コンピュータ犯罪法と著作権法の改革を求めている。[ 52 ]
報告書によると、コンピュータ詐欺および濫用法、デジタルミレニアム著作権法、電子通信プライバシー法は、セキュリティ研究者が正当なセキュリティ研究を行う際に日常的に行う行為を犯罪化し、民事罰を科すものである。[ 52 ]
(コブとミルズ 1990)