ソフトウェア技術者に向けて、バグに関する基礎知識をまとめていく新シリーズ「バグ百科事典」。第14回は、プログラマーの花形的なプロセスであるコーディングのバグを取り上げます。
バグ百科事典では、筆者が気になったバグを紹介しています。読者の皆さまに「バグの早期発見」と「バグの未然防止」に役立てていただければ幸いです。
第14回目を迎え、少しずつバグの知識が体系的に身に付いてきたことと思います。今回は、プログラマーが誰もが経験するコーディング系のバグを紹介します。
ソフトウェア開発を経験したことがない人は、「ソフトウェア技術者の仕事はコーディングですよね」と自動的に考えます。コーディングは、プログラマーの花形的なプロセスです。コーディングとは、仕様に基づいてコンピュータが理解できる言語で記述することです。自分の書いたコードを自分で動かすため、期待通りの動作をした時の達成感は非常に大きい代わりに、動作しない時は地獄の作業となります。
筆者の経験したバグを思い出すと、「このバグは、現象も発生条件も非常に複雑で、見つからなかったのは仕方がない」というバグよりも、「何で気付かなかったのだろう」という初歩的なバグの方が多いように思います。皆さんは、どうでしょうか。
エンジニアは、細心の注意を払って、プログラムを記述しますが、意図した通りの動作をさせることは簡単ではありません。場合によっては、プログラムが非常に不可解な動作をします。デバッグ時に全てのバグを検出するのが理想で、バグがデバッグの網の目をすり抜け、テストフェーズで発生しないようにしたいところです。
コーディング時には、さまざまなバグが発生します。その中で、よくあるコーディングのバグを以下に示します。なお、プログラミング言語によって若干の違いがありますので、C言語をベースとします※1)。
※1)実行結果もコンパイラによって差異がありますので、今回は、Visual Studio Community 2019を使用した実行結果で説明します。
C言語でローカル変数を使用する場合は、変数の初期化が必要です(リスト1)。
#include <stdio.h> main(void) { int data; printf("%d", data); }
リスト1は、変数を初期化せずに使用した例です。C言語では、変数を初期化しないと、何が入っているか分かりません。なお、筆者の環境では、何も表示せずにプログラムが停止しました。
ローカル変数は、設計書には書かず、その都度考えることがあります。その場合、よく似た名前の変数名と勘違いすると、意図した動作とはなりません(リスト2)。
#include <stdio.h> main(void) { int i; int input = 7; //data1とdata2が類似している int data1[] = { 1,2,3,4,5 }; int data2[] = { 3,4,5,6,7 }; for (i = 0; i <= 4; i++) { //実はdata2を使用するはずだったかもしれない if (data1[i] == input) { printf("見つかりました"); } } }
リスト2には、似た名前を使用する例題を示しました。配列にあるデータと設定値が一致している場合は、「見つかりました」と出力するプログラムです。使用しているdata1とdata2が似ているため、異なるデータを使用しているかもしれません。
ここまで分かりやすいミスはしないでしょうが、注意しましょう。特に、自動生成コードを扱う場合は、よく似た名前の変数名がたくさん出てくるので注意が必要です。
Copyright © ITmedia, Inc. All Rights Reserved.