ヌルポインタ

出典: フリー百科事典『ウィキペディア(Wikipedia)』
ナビゲーションに移動 検索に移動

ヌルポインタ英語: null pointer)とは、何のオブジェクトも指していないことを表す特別なポインタである。

プログラムではヌルポインタを、不定長のリストの終端を表したり、何らかの動作の結果が失敗であることを表したりするのに使用する。後者の用法は、nullable型英語版オプション型英語版Nothing値を使用することもできる。

ヌルポインタの値やがいかなるものかという詳細は言語によって異なる。実際的にはいかなるオブジェクトも参照しないという言語もあり、参照先を求めようとするとJavaNullPointerException)のように例外が発生するものもある。

ヌルポインタはほとんどの処理系(この場合、言語処理系プログラムだけではなく、ハードウェアまでを含めて)で、内部的に0で表現されるが、ごく希に、0でない処理系もある。言語仕様上の意味としては普通「アドレス0(あるいは他のアドレス)を指し示すポインタ」ではなく、どこも指し示さないものとされる。

ヌルポインタを未初期化のポインタと混同してはならない。ヌルポインタは、あらゆる有効なオブジェクトとも異なることが保証されている。それに対し、言語や実装によっては、未初期化のポインタはそのような保証はなく、他のオブジェクトやヌルポインタと同じになる可能性がある。

ヌルポインタはヌル値とは意味が違う。ヌルポインタは多くのプログラミング言語において「値がない(no value)」ことを意味し、ヌル値はリレーショナルデータベースにおいて「未詳値(unknown value)」であることを意味する。ほとんどのプログラミング言語では2つのヌルポインタは等しいが、リレーショナルデータベースエンジンは2つのヌル値を等しいとはみなさない(それらは未詳値を表しているので、それらが等しいかどうかはわからない)。

C言語[編集]

C言語では、すべての型の2つのヌルポインタは等しいことが保証されている[1]。マクロ NULL が処理系定義のヌルポインタ定数と定義されている[2]。C89 (ISO/IEC 9899:1990) や C99 (ISO/IEC 9899:1999) では、NULL はヌルポインタ定数を表現する物として定義され、ヌルポインタ定数は整数定数の 0 もしくは 0 を void * に型キャストしたものとして定義されている。POSIX.1-2008 では整数定数の 0 ではなく、0 を void * に型キャストした物、(void *) 0 でなければならないと定義していて、rationale にて、整数の 0 ではあってはならないと、その定義の差を明記している[3]。よって、ほぼ全ての標準Cライブラリは NULL(void *) 0 としている。そして、C89, C99 では、ヌルポインタ定数を、(void * 以外を含めた)ポイント型に型キャストした物をヌルポインタと定義している。ほとんどの実装はそのまま変換するが、C89, C99 の仕様では、整数からポインタ、ポインタから整数への型キャストがどのような結果になるかは実装依存と明記されていて、ポインタに 0 や NULL を代入したときに、ほとんどのコンパイラは数値の 0 を代入したというコンパイル結果を生成するが、数値の 0 以外を代入するというコンパイル結果を生成しても良いという仕様になっている[4]。ただし、ヌルポインタを整数に型キャストしたら 0 にならないといけない、存在するオブジェクトや関数へのポインタはヌルポインタであってはならないと規定されている。近年はほとんど無いが、歴史的には、ヌルポインタを 0 以外で表現することもあった[5]

ヌルポインタを参照して、そのメモリアドレスに読み書きしようとすると、それは何も指していないため、メモリ保護の仕組みが存在する実行環境では、通常セグメンテーション違反やアクセス違反が発生する。この場合、Unix系ではシグナルWindowsでは構造化例外処理による例外が生成され、特に対処しなければ当該のプロセスは異常終了(クラッシュ)となる。一方、メモリ保護のない実行環境、例えばx86のリアルモードでは、アドレス0000:0000は読み書きが可能であり、ヌルポインタを参照したメモリアクセスは成功しクラッシュはしないものの、不定の期待しない動作になる。ただし、ヌルポインタへの参照があえて定義されている場合もある。例えば、16ビットのリアルモードx86デバイスのためにCで記述されたBIOSコードは、ヌルポインタを参照することにより、物理アドレス0にInterrupt Descriptor Table英語版(IDT) を書く場合がある。ヌルポインタの参照をしないようにコンパイラが最適化することもできる。それにより、セグメンテーション違反を避けられるが、他の望ましくないふるまいを引き起こす。

C++[編集]

C++では、NULL マクロをC言語から継承しているため、伝統的に整数リテラル 0 がヌルポインタ定数を意味してきた[6]。C++11ではその代わりとして明示的にヌルポインタであることを表すnullptrリテラルが導入された。

その他の言語[編集]

Pascalでは綴り記号(word symbol、すなわち予約語。『PASCAL 原書第4版』§1.2)nil である。nil は、空の値を表す(『PASCAL 原書第4版』§8.1)。

そのほかにも参照型の概念を持つ言語には、言葉こそ違えど同様なものが存在する。JavaC#ではnullC++/CLI及びC++11ではnullptrVisual BasicVisual Basic .NETではNothingObjective-CRubyではnilREALbasicではNilがヌルポインタに相当するキーワードである。

歴史[編集]

2009年にアントニー・ホーアは、彼が1965年にALGOL Wの一部としてヌル参照を発明したと述べている[7]。2009年のカンファレンスでホーアはこの発明を「10億ドルの誤り」と述べた。

それは10億ドルにも相当する私の誤りだ。null参照を発明したのは1965年のことだった。当時、私はオブジェクト指向言語 (ALGOL W) における参照のための包括的型システムを設計していた。目標は、コンパイラでの自動チェックで全ての参照が完全に安全であることを保証することだった。しかし、私は単にそれが容易だというだけで、無効な参照を含める誘惑に抵抗できなかった。これは、後に数え切れない過ち、脆弱性、システムクラッシュを引き起こし、過去40年間で10億ドル相当の苦痛と損害を引き起こしたとみられる。

出典[編集]

  1. ^ ISO/IEC 9899, clause 6.3.2.3, paragraph 4.
  2. ^ ISO/IEC 9899, clause 7.17, paragraph 3: NULL... which expands to an implementation-defined null pointer constant...
  3. ^ stddef.h - standard type definitions - The Open Group Base Specifications Issue 7
  4. ^ Can a conforming C implementation #define NULL to be something wacky - Stack Overflow
  5. ^ comp.lang.c FAQ list - Question 5.17
  6. ^ Stroustrup, Bjarne (March 2001). “Chapter 5: Pointers, Arrays, and Structures: 5.1.1: Zero”. The C++ Programming Language英語版 (14th printing of 3rd ed.). United States and Canada: Addison–Wesley. p. 88. ISBN 0-201-88954-4. "In C, it has been popular to define a macro NULL to represent the zero pointer. Because of C++'s tighter type checking, the use of plain 0, rather than any suggested NULL macro, leads to fewer problems. If you feel you must define NULL. use
    const int NULL = 0;
    The const qualifier (§5.4) prevents accidental redefinition of NULL and ensures that NULL can be used where a constant is required."
     
  7. ^ Tony Hoare (2009年8月25日). “Null References: The Billion Dollar Mistake”. InfoQ.com. 2016年3月9日閲覧。

外部リンク[編集]