メモリ管理 Macの場合、アプリケーションが使用できるメモリの総量はsizeリソースで指定 される。もしsizeリソースが無かった場合、512K(だと思ったけど、違う?)な メモリがデフォルトで確保されるんだそーな。 んでそのメモリをプログラムからmalloc()して使う...え?ポインタは難しいから 使わない?甘いねワトソン君。Macは変数の量に制限があるのだ。 グローバル変数の総量は32KBまで。ローカル変数の総量も32KBまで。という 恐ろしい制限である。これは古代のメモリマネージャから来る制限らしい。 16KBの配列2つをグローバル変数で定義したらもうグローバル変数は金輪際 使えない。ってこと。 だから64KBの配列とかをどーんと取る場合、どーしたってメモリの動的割り付け をする必要が出てくる。で、この動的に取ってくるメモリ領域エリアのことを 一般的にヒープと呼ぶ。 さて。更にもう一つ問題がある。Macのメモリ管理はいわば*手動式*なんだな。 どういうことかと言えば: 起動時:[ ヒープは空だよん ] ・メモリブロックを3つ、割り当てました 状態1:[<メモリブロック1 ><メモリブロック2><メモリブロック3 > ] ・メモリブロック2を解放 状態2:[<メモリブロック1 > <メモリブロック3 > ] ・メモリブロック4を割り当てようとしました。 状態3:[<メモリブロック1 > <メモリブロック3 > ] <メモリブロック4 > う!空きメモりの合計はメモリブロック4を作れるだけ空いているのに、連続して ないから割り当てられない!! で、このような場合(フラグメンテーション。断片化と呼ぶ)、普通OSが ゴミ集め(ガベッジコレクション。以下G.C.)をやります。Mac OSもそーします。 状態4:[<メモリブロック1 ><メモリブロック3 ><メモリブロック4 > ] ところが、これをするのに普通はCPU内蔵の仮想メモリ管理機能を使うんですが、 Mac OSはそうしない。自前でやってるんですね。これが。 状態3と4だとメモリブロック3の場所が違ってるでしょ?で、プログラムの中で メモリブロック3を指していたポインタはどうなるんでしょう? あっさり迷子になるんですね、これが。 そこでMac OSの場合、ポインタで割り当てられたメモリは移動禁止にしちゃいます。 でも、全部移動禁止にしちゃうと幾ら何でも使いにくい(だってね、G.C.が全く 出来なくなるもの)ので、ハンドルというものを導入しました。 ハンドルの実体はポインタへのポインタ。下で、

はメモリブロック1へのポインタ。

は{以下同文}。 状態5:[

<メモリブロック1 > <メモリブロック2 > ] ここでメモリブロック2がG.C.で移動しても

の内容を書き換えるだけで済む。

自体の位置は変わらないので、迷子にはならない。 という仕組み。 という訳でハンドルでのメモリ確保と解放は: Handle NewHandle(Size byteCount); void DisposeHandle(Handle h); ポインタでのメモリ確保と解放も実はあって: Ptr NewPtr(Size byteCount); void DisposePtr(Ptr p); ちなみに上はカレントヒープを使うAPI。システムヒープとかテンポラリから 確保・解放するのもあります。 で、ハンドルで確保されたメモリにアクセスする場合、処理中にOSがG.C.して しまうととっても不味いので、一時的に移動禁止にする。ということが必要。 void HLock(Handle h); // G.C.しちゃ困る。とOSに通知する void HUnlock(Handle h); // G.C.したけりゃやれば?とOSに通知する 脅す訳じゃないけど、Mac OSの仕組み上ハンドルやポインタはいやって程使います んで、ポインタに苦手意識のある人は覚悟してね(^^;; その上、キャストもしまくりになるので、コンパイルは通るけど実行したとたんに お亡くなりになるとかします(ポインタの扱いが間違っていれば)。 コンパイルエラーになったらごめんなさいだけど、例えばこんな感じ。 struct foobar** hoge; unsigned char* cp; hoge = (struct foobar**) NewHandle(sizeof(struct foobar)); if (hoge==nil) return; (**hoge).foo = (unsigned char**) NewHandleClear(1000); if ((**hoge).foo==nil) return; HLock((Handle) ((**hoge).foo)); cp = *((**hoge).foo); ... HUnlock((Handle) ((**hoge).foo)); #Windowsだと自分でそう作らない限り**なんて余りお目にかかりませんが、  Macintoshだと普通に作っても**が良く出てくる。ということです。はい (EOF)