パスワードを忘れた? アカウント作成
68367 story
プログラミング

null参照の考案は10億ドル単位の過ち? 88

ストーリー by hylom
でもnullポインタ禁止と言われると面倒くさい? 部門より

あるAnonymous Coward 曰く、

quick sortの開発などで著名なアントニー・ホーア氏が、「null参照の考案は過ちであった」と考えているとの話が本家/.で取り上げられている。

3月11~13日にロンドンで開催されるQCon London 2009における、ホーア氏のプレゼンテーション概要には次のようにある。

1965年に考案したnull参照の概念は、10億ドル単位の過ちと呼ぶべきものであろう。当時自分は初のオブジェクト指向言語(ALGOL W)のリファレンスの包括的システムを設計していた。全てのリファレンスの使用が全く問題のないことを確認するため、コンパイラによってチェックを自動化することが目標であった。null参照をこれに含めるのは、非常に簡単であり、やらずにはいられなかった。

しかしこれこそがその後40年に渡り、数え切れないほどのエラーや脆弱性、システムクラッシュの原因となり、10億ドル単位の損害や苦労を引き起こしてきたのである。最近ではMicrosoftのPREfixやPREfastなど、多くのプログラム分析ツールがリファレンスのチェックに採用されてきた。さらにSpec#など最近のプログラミング言語ではnon-null参照の宣言が導入されている。これは私が1965年に却下したソリューションである。

本家/.では「nullポインタのない世界なんて想像できない。ホーア氏に責任があるのではなく、プログラマーに責任がある。でもあえて不満を言うとすればゼロ値のトレースが難しいことだろうか」といった意見など、null参照や逆参照にまつわるコメントの多数寄せられるストーリになっているようです。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • がっ!! (スコア:4, おもしろおかしい)

    by Anonymous Coward on 2009年03月05日 18時55分 (#1525627)
    ができない世の中なんて嫌い
    • かつてはぬるぽと書き込まれればがっ!と「やらずにはいられなかった」が、
      「しかしこれこそがその後」ウザいだのもういいだのと「数え切れないほどの」荒らしや論争の原因となり、
      数百単位の掲示板・スレッドの「損害や苦労を引き起こしてきたのである」。

      この記事に従えば、いずれはぬるぽがNGワードな掲示板も現れる・・・?

      # 数百単位は言い過ぎかも:p
      • by Anonymous Coward
        ぬるぽも言えないこんな世の中じゃ
  • NULLポインタが無くなると (スコア:2, おもしろおかしい)

    by Anonymous Coward on 2009年03月05日 20時13分 (#1525657)
    C言語始めたわけーもんがNULLポインタアクセスバグに嫌気がさして
    「ポインタわからん、C言語嫌い!」とか言い出したときに、
    「誰もが通る道だ」などと訳知り顔で諭す様なふりしてイジメることが出来なくなるから、困る。

    from 三流おっさんプログラマ
  • プログラミングの大半は再発明なんだから、ホーアが禁止したって、他の誰かが似たようなものを作るだけでしょう。

    まぁ、確かに、Java で null pointer exception を見た時には「おまえ、まだ、そんなことやってるの?」とは思った。

    nullの代わりにclass objectのinstanceで初期化して、messageDoesNotUnderstandを投げるって方がエレガントだとは思う。
  • Curlの例 (スコア:2, 興味深い)

    by Anonymous Coward on 2009年03月05日 23時11分 (#1525754)

    もしかしたら「Spec#」がやっている事と同じ事の紹介かも知れませんが,ちょっと Spec# は詳しくないので,代わりに Curl の例を紹介させてくださいませ.

    Curl は HTML の代わりだからプログラミング言語とは違うのでは?とか言われる事がありますが,とんでもない,れっきとした関数型チックでオブジェクト指向的なプログラミング言語であります.
    「nullの無い世界」とはちょっと違いますが,Curl には,ある変数が null か否かをコーディングの段階ではっきり意識せざるを得ない仕組みが搭載されています.

    || ←これはコメントです.
    || Something クラスの変数 obj を宣言し,初期化しています.
    || {Something} は Something クラスのコンストラクタを呼び出しています.
    {let obj:Something = {Something}}

    || null を代入しようとすると,コンパイルエラーとなります.
    || obj は null になる事が出来ない変数です.
    {set obj = null} || error

    || クラス名の前に # をつけて宣言しておけば,null になる事ができる変数となります.
    {let obj2:#Something = null}

    || obj を obj2 に代入する事は出来ます.
    {set obj2 = obj}

    || obj2 を obj へ単純に代入しようとするとコンパイルエラー.
    || obj2 は null の可能性があるからです.
    || (上で obj を obj2 に代入していますが,コンパイラはそこまでは見ません)
    {set obj = obj2} || error

    || {non-null} 関数をかませる事で,やっと代入できるようになります.
    || もしここで obj2 が null であれば,例外が投げられます.
    || さすがにそういうのは,コンパイル時には解決できないですわな.
    {set obj = {non-null obj2}}

    もちろん,わけのわからない人が何でもかんでも # をつけて null 可の変数ばかり使ってしまっては,ほとんど意味のない仕組みではありますけども.

    Java でも @NonNull アノテーションが提案されていたりするし,C++ でも,スマートポインタをうまいこと改造して同様の仕組みを作り上げる事が出来るはずです (自分なりにはやった事があります.本格的にはやってませんが).
    これからの言語は,「null か否かを意識せざるを得ない仕組み」が常識になればいいのになーと思っています.

  • オブジェクトの寿命が変数の寿命よりも短い場合には、
    実際には使われないにも関わらず参照が残っているために、
    いつまでもGCされずにメモリ上を占有してしまう、
    ということが、ままありますね。

    特に、クロージャや例外や継続がエスケープしたりしたら、
    変数の寿命とオブジェクトの寿命を一致させるのは至難の技でしょう。

    なんだかんだ言って、null的な参照はどこかで導入されたと思います。

  • nullがない世界は、
    なんだか逃げ場がない世間の様で、
    息が詰まりそうです...

    #アレ? ひょっとして俺、疲れてる?
    --
    -- LightSpeed-J
    • by eldesh (33332) on 2009年03月05日 21時28分 (#1525701) 日記
      つML
      親コメント
      • by kr (10950) on 2009年03月06日 0時41分 (#1525816) 日記

        おせっかいモードで補足すると、ML系の言語では、 「決してnullにならない」型と、 「nullになり得る(つまり値が無い場合もある)」型を使い分けることができる、 という話ですね。

        Standard MLの option型 [standardml.org]や、 HaskellのMaybe型 [haskell.org]が、 「値が無い場合もある」型として使われます。 コンパイル時の型チェックにより、 「場合分けして、値が有る場合」という場所でしか直接の値を参照できないので、 値が無いのに間違えて値を取り出そうとすることはありません。
        # 一応「値があればそれを取り出し、値が無い場合は例外を発生せよ」というライブラリ関数も用意されているので、
        # Javaのぬるぽ^H^H^HNullPointerException [sun.co.jp]と同様の動作をさせることも選べます。

        ML系言語に馴染みがない人のために、 比較的メジャーな(?)命令型言語から似たものを探すと、 C#の nullable [microsoft.com]型のようなものを連想すると分かりやすいかもしれません。

        option型やMaybe型は、参照の際に、 値が無い場合についてのケアをしないと、 必ずコンパイラに怒られるようになっています。 だから安全、というわけですが、 とはいえ、値を使う度に場合分けをするのも面倒です。 そこで例えばC#では、 nullableに対する演算 [microsoft.com]を別途定義することで、 面倒な場合分け無しに、ちょっとしたコードを書ける工夫がしてあります。 Haskellでは、これをもっと一般化させていて、Maybeは Monad [sampou.org]としても使えるために、かなり複雑な計算でも、 驚くほどすっきりと書けたりします(うまくMonadで書ければ、ですが)。

        ということで、nullにお悩みなら、ML系言語をどうぞ。:-)

        親コメント
  • by Anonymous Coward on 2009年03月05日 21時13分 (#1525694)

    [null参照の考案は10億ドル単位の過ち?]であるならば謝罪と賠償を要求しよう!

    #とか言う冗談を思いついたが、我が身の事を考えたらそんなことできないのでありました

  • すっごい滑るよ! (スコア:1, おもしろおかしい)

    by Anonymous Coward on 2009年03月05日 23時49分 (#1525785)
    ヌルヌルするよ!
  • by beatnik (31424) on 2009年03月06日 1時27分 (#1525832)
    でしょ?
  • こうか (スコア:1, すばらしい洞察)

    by Anonymous Coward on 2009年03月06日 5時34分 (#1525880)
    逆に考えるんだ。Null pointerのおかげで10億ドル市場が作られた・・・!!
  • by thorin (14200) on 2009年03月06日 11時49分 (#1526011)
    C/C++ 言語に constant 修飾子と同様に nonnull 修飾子があると便利だと前から思ってたんだけど、どうだろ?

    nonnull ポインタ変数は初期化必須で、NULL やnonull修飾子無しのポインタからの代入できないくらいで。
  • かつてメジャー言語にポインタがなかった時代、実行時エラーの主役は0除算エラーじゃった。
    (オーバーフローはチェックしてない環境も多かったから。)
    けど、0除算エラーをなくすために0をなくそうという流れにはならなかったような。

    ぬるぽや数値の0ほどじゃないけど長さ0の配列だのフィールドのないクラスだの空文字列だのも存在していることだし
    なかったらやっぱり不便だと思う。

    nullableの類いを構文に足すのは若干大袈裟な気もするなー。

  • by Anonymous Coward on 2009年03月05日 19時06分 (#1525632)
    NULLがない場合は、何で初期化したらいいんでしょうか?

    # え?NULLがあっても、NULLなんかでは初期化しませんか。そうなんですか。
    • Re:NULLがない世界 (スコア:2, すばらしい洞察)

      by Anonymous Coward on 2009年03月05日 21時15分 (#1525695)
      nullポインタ参照は、フェールセーフ的な動作だと思います。 nullがなければ、そのジャンクなポインタはnullよりも遥かに危険なものを指しているでしょう。
      親コメント
    • by Anonymous Coward on 2009年03月05日 21時26分 (#1525699)
      エラーや脆弱性、システムクラッシュの原因とならない安全なオブジェクトがあればいいんじゃないかなぁ。つかどうしてないんだろ。
      参照はがしてもSEGVらず、数値として評価したら0、文字列として評価したら空文字、代入しても何も起きず、関数としてコールしたらすぐ戻り値0で帰ってきて、パス名とかネットワークアドレスとして開いたら/dev/nullみたいな。
      親コメント
      • Re:NULLがない世界 (スコア:2, 参考になる)

        by Anonymous Coward on 2009年03月06日 1時16分 (#1525828)

        >あればいいんじゃないかなぁ。つかどうしてないんだろ。

        それれが有る言語を「高級言語」と呼びます。

        いささか乱暴な言い方ですが、高級とはおおむねそういう方角を向くことを言います。

        一方で、そういうモノを見事に動かすには結構な実行時コストがかかるわけで、
        そのコストを嫌って「自己責任でやってね」という方針にしてるのが「低級言語」。

        まず何が起きるか判ったもんじゃないC言語のレベル。
        Javaはもう少し上のレベルで、未定義とまでは言わないものの、すごく扱いづらい挙動をするだけ。
        Rubyは更に少し上のレベルで、nilもまたオブジェクトであり、かつ振る舞いが好きなようにカスタマイズできる。method_missingとか使えば「状況ごとに」振る舞いを変えることも出来る。

        まあいろいろな高級度にそれぞれの言語が位置しているわけです。

        親コメント
      • by Anonymous Coward on 2009年03月05日 22時48分 (#1525741)
        Nullオブジェクトパターンってのは正にそのためのものかと。
        言語標準として付いて欲しいという話かもしれませんが。理想のnullってのはケースバイケースなので難しいかも。
        親コメント
    • by gm_camouf01 (31675) on 2009年03月05日 23時33分 (#1525769)
      NULLが無いなら-1
      親コメント
    • by Anonymous Coward
      Javaでの話ですが「あるメソッドで使用する変数は全てメソッドの先頭で宣言し、nullを代入すること。ただしループ変数は除く」
      というコード規約を見たことがあります。なんでそんなことをするのか質問したのですが、納得できる答えはありませんでした。
      • Re:NULLがない世界 (スコア:5, すばらしい洞察)

        by Anonymous Coward on 2009年03月05日 20時05分 (#1525654)
        コーディング規約なんてのは、それなしでは異常かつ理不尽で解読できないコードを書くプログラマーに対して、異常さの範囲をコーディング規約の中に収めるためのものなのだから、それ自体が全くもって異常かつ理不尽なのはあたり前でしょう。
        たぶん数百行あるメソッドの途中で不適当な名前の変数を宣言して、実際にそれを使うのはさらに数百行後な上に例外は握り潰しみたいなコードを書いたアホがプロジェクトにいたからだろうよ。
        親コメント
        • by Anonymous Coward on 2009年03月05日 21時11分 (#1525690)
          過去にそんな人がいたかどうかは分かりませんでしたが、その規約が導入された後のソースは以下の通りでした。

          ・宣言したけど使われないprivate変数
          ・宣言したけど使われないimport
          ・一メソッドにつき数百行は少ない方で、千行オーバー当たり前
          ・例外はExceptionまたはThrowableで逃さずキャッチ
          ・捕まえた例外はisInstanceでどんな例外かしっかりチェック
          ・良く分からないエラーは適当な例外クラスでラッピングして投げ飛ばし

          どうやらアホは一人だけではなかったようです。私にはもうどうしようもありません。
          というか、どう見ても規約の前にJavaの勉強が必要です、本当にありがとうございました。
          親コメント
      • by Sakura Avalon (12557) on 2009年03月06日 1時39分 (#1525840)
        C#はごく簡単に実体の無い宣言だけの変数が作れてしまうので、覚えたての時に戦慄しました。なにせコンパイルでは何も指摘されず、すべて実行時エラーになったので…。あれも慣れなのかも知れませんが、Javaだと基本的には初期化されますしC++では参照は初期化が必須(コンパイルエラーになる)で、それ以外も未初期化変数使用はコンパイル時にWarning出すのでちょっと驚きました。あれはnullポインタより怖かった。
        もちろん実体作成しとくのが前提なのですが、最初は初心者ですしうっかりミスもありえます。

        #最近使ってないので改良されたかな。もしかしてWarningレベル上げればチェックしてくれてたのだろうか。
        親コメント
      • 単純に、
        {
        StringData *foo=null;
        ...
          foo=bar();
        ...
          if(!foo) {
            fooが設定されてない=函数barでエラー起こしたからあれこれやる
          } else {
            fooが設定されてる=函数barで正常終了したからあれこれやる
          }
        }
        と言う、C++ではそこそこある(C的な)処理ロジックをやりたかったのでしょう。#1525645 [srad.jp]で既に出されていますが(^^;

        Javaでこれを実際にやれば例外で飛ばされる以前にポインタで論理式を表記する事自体が反則なのでなんかすごく酷い邪道に思えてなりませんが…てか、C++と違ってC引きずらないでもいいんだからOOPと言うかカプセル化や継承をうまいこと使ってAPI統一すればいいものを…

        # 以下、C++的に書くけど文法極めていい加減
        Class functionTemplete {
        bool results;
        int ERR;
        function main();
        }
        とかなんとかテンプレート作っておいて各実装はこのクラスの下位のクラス内ローカルな関数かこのテンプレを継承したクラスとして実装してねー、このテンプレに載せてある関数名と変数名は予約語扱いでこういう意味持たせておくインタフェース用の変数だよ。的な比較的ルーズなやり口が通用するというのに(あ、排他しないといけない可能性があるから、厳しくやるには変数いじらせる時はこの関数をこう叩けにしなきゃだめな場合も出るか)…そもそもJavaをわざわざ使う最大のメリットって、オブジェクトのポータビリティと同時にこの辺にある気がするのですが(あ、あくまでもいつもはCとアセンブラだけの人の偏見です ^^;)…

        まぁ、一度手慣れた手法を崩すのが容易ではないのは分かりますが。

        --
        --暮らしの中に修行あり。
        新しいblogはじめました。 [hateblo.jp]
        親コメント
      • by Anonymous Coward

        Cの後遺症かな

  • by Anonymous Coward on 2009年03月05日 19時14分 (#1525636)

    ほ、ほーっ、ホアアーッ!! ホアーッ!!

  • by Anonymous Coward on 2009年03月05日 19時14分 (#1525637)
    C FAQ [kouno.jp]を読んでると目がヌルヌルしてきます
  • by Anonymous Coward on 2009年03月05日 19時49分 (#1525646)
    音の響きがすきだけどね。
  • by Anonymous Coward on 2009年03月05日 19時59分 (#1525650)
    当時の水準ではそんなもんでしょう
typodupeerror

UNIXはシンプルである。必要なのはそのシンプルさを理解する素質だけである -- Dennis Ritchie

読み込み中...