娘のためにその3:メモリ書き込み[30分]

娘に読ませる以外の意図はなく、よって質問や指摘には対応していません。すなわちネットの浄化作用が働いていない不正確な内容になりますので、正しい情報を求める方は閲覧をご遠慮ください。公開しているのは、通信手段としての利便性のためです。

まずは Arduino のプログラムの特徴を説明しておこう。Arduino IDE から「新規ファイル」を選択すると以下のような状態になっているはずだ。

void setup() {
 // put your setup code here, to run once:

}

void loop() {
 // put your main code here, to run repeatedly:

}

ここに見える英文はちゃんと読んでおこう。このように // とスラッシュがふたつ重なっていたら、そこより右には何を書いても無視されるC言語のルールがある。なので、プログラム中には自由に説明文を書くことができるのだ。これをコメント文という。

よく、「プログラムにはなるべくコメントを書け」と言われる。意図を自然言語で残しておくことは自分にとっても有用だからだ。現代では、ほとんどの環境で日本語で(全角で)コメントを記述するのが許容されている(昔はエラーが出ることもあった)。また、歴史が30年も40年もあるので、コメントの議論が成熟し、一周まわって「コメントに頼るな」「書いたら負け」のように言われたりもする。まあ最初のうちは、コメントは書いた方がいい、と覚えておこう。

ここのコメントにあるとおり、setup に書いたものは起動時に一度だけ、そして loo pに書いたものは繰り返し何度も実行される。

では次のプログラムを実行させてみよう。

void setup()
{  
    Serial.begin(9600);
    Serial.println("hello");
}

void loop()
{
}

これを実行した結果、コンソールに hello と表示されるのを確認しよう。コンソールとは「ツール」→「シリアルモニタ」で表示されるwindowである。つまりこの Serial.println (シリアル プリントエルエヌ)にはコンソールに文字列を表示させる機能がある、というわけだ。この先は Serial.println を使用し、プログラムの動作を確認していく。

ではいよいよ、メモリに何かを書き込んでみよう。次のプログラムを実行する。

void setup() {
    *(int*)200=100;
}

void loop()
{
}

200というアドレスが指し示すメモリに、100という数値を書き込むプログラムが実行される。本当に100が書き込まれているか確認するために、次のプログラムを実行してみよう。

void setup()
{  
    Serial.begin(9600);
    *(int*)200=100;
    Serial.println(*(int*)200);
}

void loop()
{
}

実を言えば、これを試してみて驚いた。このプログラムは実行できてしまうし、ちゃんとコンソールにも100が出力される。なんらかのエラーが出ると思っていたのだが・・

エラーを予想した理由を説明する前に、ここで micro:bit のスペックを確認してみよう。"micro:bit specifications" でググってみる。Hardware - Micro:bit developer community(https://tech.microbit.org/hardware/)というページが見つかるだろう。開くと、スペックが掲載されており、

RAM 16KB

と書いてある。つまりこの micro:bit のメモリ容量は 16KB だ。16キロバイト。ここの「キロ」は 1024 なので、16 x 1024 = 16384 bytes 。つまりアドレスは1万6千ぐらいの範囲がある。ただしいくつから始まっているかはわからない。

上の例では単にアドレスを 200 と指定した。この200番地というのが、正しくメモリを指しているとは限らない。メモリはもっと大きな数値のアドレスに存在するのが普通だ。

では micro:bit において、メモリがどのアドレスにあるのか確認しみよう。

char buf[300];
void setup()
{
    Serial.begin(9600);
    Serial.println((int)buf);
}

void loop()
{
}

先頭の一行は、正しい作法で300bytesのメモリを確保している。buf は勝手に付けた名前で、なんでもいい。バッファのつもりでそうしている。println でそのアドレスを表示している。手元で実行すると 536879244 という値が表示された。そう、アドレスというのはそのぐらい大きな値が割り当てられているのが普通だ。

一般論として、自由に使える領域があったとして・・そう、例えば黒板の好きな場所に何かを書き込めるとして。自分がこれから書き込もうとしている場所が、既に他の人によって使用されていないことを確認する必要があるのは、納得してもらえるだろう。そうでなければ「既に書き込まれていた意味のある値を破壊してしまう」あるいは「自分が書いた値が何者かに破壊されてしまう」といったことが起きてしまう。

メモリそのものは決して難しい概念ではない。アドレスを指定したら読み込むのも書き込むのも難しくはない。難しいのは、それを管理すること、つまりそこにアクセスしているのが自分のプログラムだけであることを保証することだ。管理されていないメモリを扱うと、高い確率でプログラムは誤動作する。一般的にコンピュータのクラッシュというのは、ほとんどがこの、メモリへの不正アクセスが原因なのだ。

今回の例にあげた「200というアドレスが指し示すメモリに、100という数値を書き込む」というのは、完全に不正アクセスだ。やってはいけない例をあえて例示したわけだが、これが「やらかしている」ことを実感して欲しい。間違ったプログラムというのはけっこう簡単に書けてしまうのだ。micro:bit のように完結したデバイスを教材にしたのは、不正アクセスで何が起きてもいいように考えてのことだ。

繰り返しになるが、メモリは管理する必要がある。つまり確保してから使用する必要があるのだ。そして決して確保した領域の外に書き込んではいけない。土地と同じで、どんなに広いからといっても好きに使えるわけではない。プログラムが難しいとしたら、この事情が主因だ。逆に言えば、これさえ気をつけていればプログラムの勘所は抑えていることになる。

つづく

この記事が気に入ったらサポートをしてみませんか?