1980年代、筆者が高校生・大学生だったころに「C言語がすごい」という話を友人から聞いていた。しかし、当時の筆者が触れていたのはMSXパソコンのBASICと大学の汎用機のFortranくらいだった。C言語をやっと手に入れたのは、1992年の暮れである。清水の舞台から飛び降りるような気持ちでBorland C++の大箱を買って帰った。

 それから20年近くが経過した今でも、C言語は「最強のプログラミング言語」と呼ぶべきポジションを確保し続けている。UNIXオペレーティングシステムとC言語が世界に与えたインパクトの大きさは、実に大きなものがあった。

 ただ、C言語を学習したり評価したりする際には、C言語の大きな欠点を知っておく必要があるだろう。筆者が考えるその大きな欠点とは、「文字列の扱いが非常に面倒」であることだ。

「バッファオーバーフロー」を回避するのは大変

図1●C言語で作成した、入力された文字列を出力するプログラム(inout.c)
図1●C言語で作成した、入力された文字列を出力するプログラム(inout.c)
[画像のクリックで拡大表示]

 例を示そう。図1はC言語で記述した、ユーザーが入力した文字列を出力するプログラムの例だ。4行めで文字型(char)の配列bufferを宣言し、5行めでgets関数を使ってユーザー入力をbufferに受け取る。6行めのprintf関数でbufferの内容を出力する。whileでそれを繰り返す。ユーザーがEnd Of File、WindowsならCtrl+Zを入力すると終了する。

 図1のプログラムで問題なのは、bufferの大きさが固定(ここでは10文字分)であることだ。ユーザーが9文字を超える文字列を入力してくると、このプログラムは正しく動かない。これをC言語プログラムの「バッファオーバーフロー」と呼ぶ。

 だったら、bufferをもっと大きくすればいいじゃないか?と思われるかもしれない。それはそうなのだが、大きくするとメモリーを無駄に消費する。しかも、bufferをいくら大きくしたところで、問題は解決しない。バッファオーバーフローを意図的に発生させたいのであれば、やたらと長い文字列を与えればいいだけの話だ。

 さらに面倒なことに、図1のプログラムは、9文字を超える文字列を入力したとしても、一見まともに動いているように見えるケースがある。メモリーを不正に使っていても、不正に使った領域がたまたま空いていれば、なんとなくテストを通過してしまうことがあるのだ。これだと問題を見過ごす可能性が大きくなる。

 C言語で、固定バッファのオーバーフローを生じさせない形で文字列を受け取ることはできないのだろうか。もちろんできる。ムック「ゼロから学ぶ!最新C/C++」の24ページには、バッファを何度も繰り返し利用して、ファイルから読み込む文字列の長さの制限をなくした例を掲載している。

 でも、こうしたコードを書こうとしても、なかなかうまく記述できない。筆者も自分で書いていてうんざりしたくらいだ。人から依頼を受けて書くとしたら、きっと図1のような簡単なコードを書き、「1行約6万5000字を超える入力はできません」などと、こっそりどこかに注意書きを書くのだろう。で、ユーザーがそれに気付かないという事態を招くわけだ。このような可能性を取り除くことができないのは、C言語の大きな欠点である。