プログラマにとって最も避けたいモノ ‐ ハングアップ ‐ 対策の知恵①

ハングアップはまだマシ

バグや外部からの予想外の入力によって動作や出力が異常な状態になってしまうことがあります。
プログラマにとってはそれが日常であり、その抗いがたい現象との闘いの日々でもあります。

プログラムの動作に異常が発生しても、それが直接目に見える様な状況は、滅多に無く、多くの場合は、内部の異常状態によって引き起こされた、様々な現象に変化して現れます。

GUIの表示がおかしくなったり、出力されたファイルがおかしかったり、機器の挙動がおかしくなったりする場合もあれば、プログラムが突然終了してしまったり、停止したりする場合もあります。

その現象がささやかなものであれば、後からそっと直すだけで済むかもしれません。
あるいは、ハングアップすれば、プログラマーは問題の発生に気づき、対策する機会を得られるので、まだ幸せかもしれません。

それよりも、不幸なのは、問題が隠れてしまうことです。

前回のプログラムを例に考えてみましょう。

PROFILE *get_profile(int i)
{
    return &table[i];
}

void print_profile(int i)
{
    PROFILE *p = get_profile(i);
    printf("number=%d, age=%d, name=%s\n", p->number, p->age, p->name);
}

i が範囲を超えた場合の挙動について。

もし、table の隣に似たような変数があった場合、ハングアップには至らず、その意図しない変数の値を、正しい値と信じて、動作を続けてしまうかもしれません。

すると、どんなことが起こるでしょうか?

例えば、その変数に200と入っていた場合。
プログラムは順調に稼働している様に見え「**さんは200歳」と表示されるかもしれません。

そうなると、プログラムは一見正常に動作している、あるいはPCの中でそんなプログラムが動作しているなど知らないオペレータからしてみれば、プログラムのバグなどと想像だにしないかもしれません。結果、大騒ぎに発展してしまうかもしれません。

例えば、その変数が身長を示す変数であった場合。
**さんの年齢を20歳と入力したら、代わりに変数にその値が代入されてしまい、○○さんの身長は20cm、と記録されて、翌年になってから大騒ぎになってしまうかもしれません。

関数の引数は必ずチェック

外部からもらった値を過信してはいけません。

例え、その関数が自分で作った自身のあるプログラムから呼ばれる場合でも、です。

後日、その関数をBさんが別のプログラムで使用するかもしれません。
そして、引数として範囲外の値を渡してくるかもしれません。
それが単純なミスであれば、あなたが責められることはないかもしれませんが、気分の良いものではありません。自分が作った関数でハングアップするのですから。

場合によっては、その引数には正当な理由があって、範囲外の値を渡す結果となったのかもしれません。

例えば、仕様変更。仕様変更により、listの上限が100から200に変更された場合。

使用する関数の中身を精査しなかったBさんが悪いのでしょうか?
最低限のチェックを盛り込まなかった自分が悪いのでしょうか?

責任の行方は分かりませんが、バグによって少なくない影響が発生するでしょう。

謝罪でしょうか?残業でしょうか?プログラムの作り直しやチェックのやり直しでしょうか?
モチベーションや雰囲気の悪化で済むでしょうか?クライアントへの謝罪や交渉で出張でしょうか?

少しぐらい面倒でも引数のチェックを入れた方が遥かにましです。

最悪の状況を考えれば、面倒を感じるよりも、安心を感じるのではないでしょうか。