2012年07月26日

メモリイメージ再び

晴れ夏です!
毎日暑い日が続きますねあせあせ(飛び散る汗)
完全にタンクトップ化してしまった「オクダ」です。

今日は前回の「メモリイメージ」の続きでメモリについて更に深く掘り下げていきます。

前回、4スタック
に関しては存在を紹介しただけでサラッと流してしまいました。
まずは「スタック」とはどういうモノなのか掘り下げていきましょう。

スタックをウィキペディアで調べてみましょう。
説明が多岐にわたっていて難しいかもしれません。

重要なのは「後入れ先出し」という事と、そのイメージになります。
買ってきた本をどんどん積み上げていって、読む時は上から順番に取り出します。
途中や下から抜き出すような事をしません。

プログラムにおけるスタックも同じでメモリの最後のほうから順に積み上げていき、
新しい物から取り出します。
この動作を push - pop と言います。

様々なデータを扱う時に使用されるデータ構造ですが、プログラムの根幹部分でもこの仕組みを使用しています。
あまりにも使用頻度が高いのでCPUでハードウェア的にサポートしているくらいです。
どこで使われるかと言うと「関数呼び出し」です。

ほとんどのプログラミング言語では関数呼び出しがあります。
呼び出された関数の中で更に関数を呼び出し、そこから更に関数を呼び出し、更に関数、、、、
と言った具合にプログラムしていると思います。
視点を変えると、
ある関数を処理していたら関数呼び出しがあるのでその関数にジャンプして、その関数内で更にジャンプして、、、、
と言う事になります。
そして、関数の最後やreturn命令まで辿り着くと呼び出し元へ戻っていきます。
このような動作を繰り返してプログラムが動いています。

さて、関数をどんどん渡り歩いていくわけですが、戻り先を憶えておかないと迷子になってしまいますよね。ふらふら
そこで登場するのが「スタック」です。
関数にジャンプする時に戻り先をスタックに積みます。
どんどんジャンプしてもどんどん積んでいきます。
戻る時はスタックから取り出せば戻り先がわかります。
どこまで深く潜っても出たり入ったりしてもスタックを頼りに元の場所に戻ってくる事が出来ます。
イメージできますか?

スタックには戻り先と一緒に様々な情報を積んでいきます。
CPUのレジスタ(CPUで使用する変数のようなモノ)は有限なので
今の関数で使用しているレジスタの状態をスタックに保存しておいて、ジャンプして戻ってきた時に復元しています。

ローカル変数もスタックから確保します。
情報を積み上げるモノだと説明したので少し変な感じがするかもしれません。
もう少し詳しく説明しましょう。

ジャンプする時にスタックに戻り先を積むと説明しましたが、関数にジャンプしてきてすぐにローカル変数をスタックに積みます。
その領域を変数のメモリとして使用します。
配列なども、そのメモリサイズ分スタックに積みます。(スタックから確保します)
モチロン、関数を抜ける時にはスタックから取り出します(領域を破棄します)

場合によりますが、関数の引数もスタックを経由して受け渡される事もあります。

ちっ(怒った顔)
イロイロいっぱい書いてきたので難しくなってきましたね。
細かい事はともかく、スタックには戻り先やローカル変数が積まれるという事が重要です。
このローカル変数には配列も含まれます。
配列外にアクセスしたらどうなりますか?がく〜(落胆した顔)
関数の呼び出し元や少し前に呼び出した関数でスタックした情報の残骸が今のスタックの前後にあります。
変数や配列を未初期化の状態で使用したり、配列外の情報を読み出した場合にはスタックの状態に依存した情報にアクセスする事になります。
読み出しはともかく、書き込みをするとどうなるか、、、、がく〜(落胆した顔)
戻り先を書き換えた時には何が起こっても不思議ではないです。

関数の呼び出し順番や、途中に無意味な関数を追加しただけで動作が変わるようなバグは
このような状態で作りだされる事がよくあります。
何も表示しない print を追加すると動作が変わったりするバグに遭遇した事ないですか?

ローカル変数のアドレスを憶えておいてその内容を後で参照したらどうなるでしょう?
ローカル変数の内容やアドレスが有効な期間もイメージできたと思います。
関数を再帰呼び出しした時のローカル変数はどのようにして確保されているかなど
スタックの仕組みとメモリを理解する事で動作のイメージがわかってくると思います。

思わぬ動作をするバグに遭遇したらスタックも疑ってみてください。
風が吹けば桶屋が儲かるように、ソースコードからは想像できない仕組みでバグが産み出されている事があります。

今回は少しややこしい話をしました。
基本的な事でありながらあまり知られていない事だと思います。
スタックの知識があるだけでプログラミングやデバッグのスキルがワンランクアップしますよ!ぴかぴか(新しい)


posted by 管理人 at 23:17 | プログラミング