SilentC のメモリ管理をのぞく [ColdFire V2]
SilentCには、メモリ割り当て関数 MemoryAlloc が用意されています。 どんなメモリ管理が行われているのか、ちょっとのぞいてみましょう。
割り当て限界を見る
MCF52233には、32KByteのRAMが搭載されています。 この32KByteのメモリを MemoryAlloc でどのぐらい割り当ててくれるのか、調べます。 調査方法は、 MemoryAlloc 関数を何度も呼び出す方法をとりました。
SilentC (May 13 2008) OK PrHex(MemoryAlloc(256)) 20003934 OK PrHex(MemoryAlloc(256)) 20003a38 OK PrHex(MemoryAlloc(256)) 20003b3c OK : PrHex(MemoryAlloc(256)) 20007c3c OK PrHex(MemoryAlloc(256)) 20007d40 OK PrHex(MemoryAlloc(256)) 20007e44 OK PrHex(MemoryAlloc(256))
256バイトのメモリを割り当てていくと、0x20007e44から0x20007f43までの256バイトを割り当てたところで、SilentCは、どこかに飛んでいってしまいました。 どうやら、ヒープ領域の上限は、このあたりにありそうです。
管理領域には何があるのか
割り当てられているアドレスを見てみるとわかるように、割り当てた領域よりも4バイト多くアドレスが進んでいます。 おそらく、この4バイトに何らかの管理情報が含まれているのだと考えられます。 何があるのか、ダンプしてみます。
PrHex(MemoryAlloc(256)) 20003934 OK PrHex(MemoryAlloc(256)) 20003a38 OK m::d(0x20003a00) 20003a00 00 00 00 00 00 00 00 00 ........ 20003a08 00 00 00 00 00 00 00 00 ........ 20003a10 00 00 00 00 00 00 00 00 ........ 20003a18 00 00 00 00 00 00 00 00 ........ 20003a20 00 00 00 00 00 00 00 00 ........ 20003a28 00 00 00 00 00 00 00 00 ........ 20003a30 00 00 00 00 00 41 00 40 .....A.@ 20003a38 00 00 00 00 00 00 00 00 ........ 20003a40 00 00 00 00 00 00 00 00 ........ 20003a48 00 00 00 00 00 00 00 00 ........ 20003a50 00 00 00 00 00 00 00 00 ........ 20003a58 00 00 00 00 00 00 00 00 ........ 20003a60 00 00 00 00 00 00 00 00 ........ 20003a68 00 00 00 00 00 00 00 00 ........ 20003a70 00 00 00 00 00 00 00 00 ........ 20003a78 00 00 00 00 00 00 00 00 ........
0x20003a38からの256バイトのブロックの直前には、00410040という4バイトの値が入っていました。 これは、何かな? 割り当てるブロックのサイズを変えながら、値を調べてみました。
サイズ | ブロック先頭 | 管理領域アドレス | 管理領域内容 |
---|---|---|---|
16 | 20003934 | 20003930 | 0005 0004 |
32 | 20003948 | 20003944 | 0009 0008 |
48 | 2000396c | 20003968 | 000d 000c |
64 | 200039a0 | 2000399c | 0011 0010 |
80 | 200039e4 | 200039e0 | 0015 0014 |
96 | 20003a38 | 20003a34 | 0019 0018 |
112 | 20003a9c | 20003a98 | 001d 001c |
128 | 20003b10 | 20003b0c | 0021 0020 |
管理領域の2ワード目は、割り当てたブロックサイズの4分の1の値になっていました。 そのため、ここには、ロングワード(4バイト)単位のブロックサイズが入っているのだろうと推測します。
メモリを開放すると管理領域はどうなるか
管理領域の1ワード目の数値の意味は、これだけでは不明です。 そこで、1024バイトの領域を確保・開放して管理領域の変化を調べました。
PrHex(MemoryAlloc(1020)) 20003934 OK PrHex(MemoryAlloc(1024)) 20003d34 OK MemoryFree(0x20003934) OK PrHex(MemoryAlloc(1024)) 20004138 OK PrHex(MemoryAlloc(1024)) 2000453c OK MemClear(0x20003d34,1024) OK MemClear(0x20004138,1024) OK MemClear(0x2000453c,1024) OK MemoryFree(0x20004138)開放したメモリは、すぐにインタプリタの作業領域にされてしまうようなので、少々、トリッキーな事をしています。 管理領域の前後はこのようになりました。
20004120 00 00 00 00 00 00 00 00 ........ 20004128 00 00 00 00 00 00 00 00 ........ 20004130 00 00 00 00 01 01 01 00 ........ 20004138 00 00 00 00 00 00 00 00 ........ 20004140 00 00 00 00 00 00 00 00 ........ 20004528 00 00 00 00 00 00 00 00 ........ 20004530 00 00 00 00 00 00 00 00 ........ 20004538 01 01 01 00 00 00 00 00 ........ 20004540 00 00 00 00 00 00 00 00 ........ 20004548 00 00 00 00 00 00 00 00 ........
確保された状態でも、開放された状態でも管理領域の値には変化がありません。 ということは、1ワード目は、単に管理情報を含んだメモリブロックの長さということも考えられます。 空エリア情報が管理領域に書いてあるわけではなかったのか。
4バイトの管理領域があることを発見したときには、MS-DOSのような管理方法かと思っていたのですが、どうもそうではなさそうです。 ここから先は、リバース・エンジニアリングかな?
関連文献
私に記憶にあるMS-DOSのメモリ管理方法は、この本で読んだ知識だったはずです。
この記事の「割り当て限界を見る」で「MemoryAllocを繰り返すと暴走する現象」について言及しました。「SilentC (Oct 14 2008)版」では、割り当て可能なヒープが枯渇した場合には、MemoryAllocが0を返すように修正されました。
by noritan (2008-10-15 21:26)