C言語入門|オーバーランを防ぐ3つの領域

ここまでで、文字列がとても便利である一方、
一歩踏み外すと即オーバーランにつながる危険な存在
だということが見えてきました。

でも、安心してほしい。
オーバーランを完全に運任せにしなくても、
意識するだけでリスクを大きく下げる考え方があります。

それが、
「文字列に関する3つの領域」を明確に区別することです。

文字列を「かたまり」で考えない

私たちはつい、文字列をこう見てしまいます。

hello という5文字のデータ

でも、C言語にとって文字列とは、
連続したメモリ領域の中での使われ方 にすぎません。

たとえば、次の宣言を見てください。

char str[10] = "hello";

この1行で、
「hello」という文字列

「10バイトのメモリ領域」
が同時に生まれています。

ここを曖昧に理解していると、事故が起きます。

メモリ上の実際の姿を見てみよう

この宣言を、メモリの並びとしてイメージすると、次のようになります。

文字コードにすると少し生々しいですが、
ここに 非常に重要な区切り が存在しています。

文字列に関する3つの領域

C言語で文字列を扱うときは、
次の3つの領域を常に頭の中で分けて考えます。

使用中の領域

  • 先頭文字から
  • 最初に現れる \0 まで

この範囲が、
今まさに文字列として使われている領域です。

見た目の文字数より、
必ず1バイト多い
という点が重要です。

使用可能な領域

  • 配列宣言
  • malloc

などで 正式に確保した範囲です。

まだ文字は入っていないけれど、

  • 文字を追加できる
  • 書き換えてもよい

という、安全な余白です。

使用禁止の領域

  • 確保していない領域
  • 配列の外
  • 他の変数の領域

ここは 絶対に触れてはいけません

読み取りも書き込みも、
どちらもオーバーランです。

多くの事故は「領域の混同」から起こる

オーバーラン事故の多くは、
次の勘違いから生まれます。

  • 使用中と使用可能を同一視する。
  • \0 の存在を忘れる。
  • 配列サイズを意識しない。

つまり、

「まだ空いてそうだから大丈夫」

という感覚が、
C言語では通用しないのです。

安全な文字列操作の第一歩

文字列操作に慣れてきた人ほど、
この3つの領域を 無意識に切り替えながら コードを書いています。

  • 今どこまでが使用中か
  • どこまでが使用可能か
  • これ以上は危険か

これを考えるクセを身につけるだけで、
オーバーランの危険は激減します。

「見えない境界」を意識する

文字列は、
目に見える文字だけで成り立っているわけではありません。

  • 見えない \0
  • 見えない配列の終端
  • 見えないメモリの壁

それらを意識できたとき、
あなたは C言語の文字列を安全に扱える側の人間 になります。