Null Pointer とは?何も指さない参照
null pointer は意図的に何も指さない参照で、「ここに値はない」を意味するために使われます。本物のオブジェクトを指しているかのように使うと、エラーや crash を引き起こします。
ポインタと参照は何らかのオブジェクトのアドレスを保持します。null pointer は「何も指さない」という特別な値で、不在を表す方法です。問題は、コードがポインタは有効だと仮定し、それが指すものを使おうとするときに始まります。その null pointer の dereference はソフトウェアで最も一般的なバグの 1 つで、有名にも「10 億ドルの誤り」と呼ばれています。
null が表すもの
null(言語によっては nil、None、nullptr)は「オブジェクトなし」を意味する番兵です。格納したり、渡したり、チェックしたりするのは全く問題ありません。危険なのはそれを dereference すること、つまり指していないオブジェクトを求めることだけです。
null の dereference が何をするか
null の dereference は言語ごとに異なる挙動をします。Java では NullPointerException、JavaScript では TypeError、C では segmentation fault です。いずれの場合も、コードが値を期待して何も得られなかったことを示します。
言語が null からどう守るか
- 空のケースの処理を強制する Optional や Maybe 型。
- nullable と non-null の参照を分ける、型システムにおける nullability。
- null で short-circuit する optional chaining のような null-safe な演算子。
- null の可能性がある参照を dereference する前の防御的なチェック。
なぜ null は多くのバグを引き起こすのか
多くの言語ではどんな参照もこっそり null になりうるため、コンパイラは警告できません。エラーは runtime でしか現れず、特定の経路が実際に null の値に当たったときに起こります。それは本番の奥深く、あるいはめったに実行されないテストの分岐かもしれません。
簡単な例
JavaScript では const user = null; user.name; は、何もないものからプロパティを読もうとするため throw します。optional chaining(user?.name)は throw する代わりに undefined を返します。
CI における null pointer
テストでの null dereference の crash は決定的なロジックのバグなので、毎回同じように失敗し、retry では直りません。Latchkey は一時的なインフラの失敗だけを retry し、再現する null pointer の crash は見えるままにするため、根本のバグがきちんと修正されます。
重要なポイント
- null pointer は値の不在を表します。バグはそれを dereference することです。
- null の dereference は、マネージドな言語では exception を、非マネージドな言語では segfault を起こします。
- 決定的なロジックのバグなので、CI で retry しても役に立ちません。