PR

 グローバル変数や循環参照オブジェクトをやたらと使ってはいけない。やみくもに使ってしまうと,意図しないバグに悩まされたり,サービスがダウンして夜中に呼び出されたりといった悲しい事態に陥ることになる。

 なぜ使ってはいけないのか。

グローバル変数の危険性

 グローバル変数とは,名前空間という変数や関数(あるいはメソッド)の名前と実態を,プログラム全体で共有している変数のことだ。特に断りが無い場合は,ソースコード中のどこからでも参照,変更が可能である(図1)。

図1●グローバル変数
図1●グローバル変数
グローバル変数はどのソースコードからも参照できる

 一方で特定の範囲でしか参照・変更できない変数をローカル変数と呼ぶ。ローカル変数はその特定の領域を超えたり,あるいはどこからも参照されなくなったりすると,自動的に消える変数と考えてよい。これらの違いを前提に考えると,自分の宣言したグローバル変数が自分の意図していない個所で変更されるかもしれないという危険性がある。

 例えば,業務で定数のように扱っているグローバル変数があるとしよう。特定の条件で異なる処理を呼び出した際に,不幸にも自分の宣言した定数が書き換えられて,ある条件下で必ず計算が食い違うなどという現象が起きかねないのだ。グローバル変数の宣言や参照,変更がソースコードのあちこちに散らばっている場合は,原因の特定にも相当時間がかかる。

グローバル変数を使わない

 仮に,グローバル変数を設定値のように使いたいのであれば,定数を用いるべきである。また,グローバル変数はmod_perl,mod_python,mod_ruby,fastcgiといった永続化環境においてグローバル変数は致命的なバグを生み出す可能性がある。普通のCGIであれば,グローバル変数はリクエストごとに初期化されている。しかし,永続化環境においては初期化は起動時のみで,その後ずっと同じ変数を保持し続ける。やむなく使う場合は,変数名を大文字にするなど識別しやすい命名規則によって人的ミスをなるべく引き起こさないような注意が必要だ。

循環参照の危険性

 循環参照とは,構造化されたデータの子孫に自分自身が参照されているようなケースを指す。オブジェクト指向言語だと,特定のオブジェクト・プロパティにそのオブジェクトを代入をすると循環参照しているオブジェクトができてしまうケースがある(図2)。

図2●循環参照
図2●循環参照

 このような循環参照オブジェクトは本来,その変数の影響範囲であるスコープから外れた場合,自動的にガーベジ・コレクションという不要な変数割り当てを解放する機能によって破棄される。だが,メモリー内に残されたままになってしまうケースがある。そうなると,メモリー・リークを起こし,プログラムが正常に動作しなってしまう。

 循環参照が永続化環境で存在する場合は,リクエストごとに少しずつメモリー使用量が増えていく。もし,メモリー使用量がだんだんと増えていくようであれば,Linuxならsarなどのシステム監視ツールを使って,循環参照を行っている個所が無いか確認するとよい。循環参照を検出するツールは各言語でそろっているので,それぞれ適切なツールを使って循環参照が無くなるようにするべきである。

 このようにグローバル変数や循環参照はプログラムのバグやトラブルのもとになるケースが非常に多い。安易に使ってはいけない。


山口徹
サイボウズ・ラボ
 サイボウズ・ラボ株式会社のプログラマ。バーテンダーからIT業界に転身後,様々なWeb制作を行い,大規模コミュニティ・サイトの開発・運用を経て,現在は研究開発の日々。Perl使い。Perlを中心とした開発のノウハウやネタをShibuya Perl Mongersのイベントで発表するなど講演活動も行う。個人の開発日記は「Yet Another Hackadelic」。仕事のブログは「log4ZIGOROu」。