ショートカット
ファシリテーター × あり方
コーディングの向こう側
Hello, ANOTHER world!
オブジェクト指向のはなし
プログラミングのはなし
C言語実力診断クイズ
eSkillBooks
プログラミングのはなし

ポインタを 0 にする

いろいろな解説書に書いてある通り、dangling pointer(参照先がすてに解放されてしまっているためアクセスするとシステムエラーを起こすポインタ)は非常に危険です。どうやったら、dangling pointer を避けることができるでしょうか?

簡単です。たったひとつのガイドラインを導入すれば済みます。

ガイドライン: オブジェクトを参照していないポインタは 0 にする

これだけです。

次の悪い例を見てください。

SAMPLE
CODE
void main()
{
    int *pi;
    {
        int i = 0;
        pi = &i;
        *pi = 100;
    }

    cout << *pi << endl;
}

上の短いプログラム中で、変数 pi は2度も dangling pointer になっています。わかりますか?

  • 1度目: 宣言時に初期化していないため、不定アドレスを指している。
  • 2度目: 内側のブロックを抜けたときに変数 i が解放されるため、スタック上の不正なアドレスを指している。

とくに2度目は危険です。多くの処理系では正常に動作するように見えるかもしれませんが、スタック上の解放された領域を指すようなアドレスは絶対に使用してはいけません。解放された領域はもはやシステムのものなので、プログラムから安全に使用できることが保証されていないのです。プログラマが触ってはいけない部分です。

この悪いプログラムを直してみましょう。まず、さきほど述べたガイドラインを導入します。

SAMPLE
CODE
void main()
{
    int *pi = 0;
    {
        int i = 0;
        pi = &i;
        *pi = 100;

        pi = 0;
    }

    cout << *pi << endl;
}

改善された点は次の通りです。

  • 変数 pi に初期値を与えた。
  • ブロックを抜けるとき、変数 pi が不正なアドレスを指す前に 0 でクリアした。

この改善の結果、cout のところでシステムエラーが発生するようになりました。これは、ポインタを 0 にするガイドラインを導入したためにバグが発生したということではありません。もともとコード中に含まれていたバグが、このガイドラインによって表面化したのです。

これでコード中のアルゴリズムが誤っていることがわかったので、修正が必要になりました。しかし、もはや誤りの正体がわかっているので、修正は簡単ですね。

(「プログラミングのはなし」は1998年1月から1999年1月にかけて作成されたコンテンツです。)