実例を使って説明する。
void demo01(AComArg *ca0)
{
ABegin(ca1, c1, ca0);
void *p;
int i, alc0, ofs, id;
AMemAlc0 *t28[28]; AMemAlc1_makeTable28(ca1, ca1->ta, t28, 0); // idを得るための下準備.
for (i = 0; i < 7; i++) { // このループで7つのポインタを取得する.
static int t[7] = { 1, 4, 1, 4, 2, 1, 3 };
p = AMemAlc1_alc(ca1, ca1->ta, 8 << t[i], c1); // 16, 128, 16, 128, 32, 16, 64 バイトのメモリを取得.
id = AMemAlc0_test3(ca1, t28, t28 + 28, p, &ofs, &alc0); // 取得したポインタのidを得る.
printf("#%d: 0x%08x id=(%d,%d,%d)\n", i, (int) p, alc0, id, ofs); // それを表示.
}
AClean_out(ca1, c1);
}
このプログラムを三度実行すると以下のようになる。
#0: 0x007b36e8 id=(1,0,0)
#1: 0x00610048 id=(4,0,0)
#2: 0x007b36f8 id=(1,1,0)
#3: 0x006100c8 id=(4,1,0)
#4: 0x00614458 id=(2,0,0)
#5: 0x007b3708 id=(1,2,0)
#6: 0x00618868 id=(3,0,0)
#0: 0x00b136f8 id=(1,0,0)
#1: 0x006e0048 id=(4,0,0)
#2: 0x00b13708 id=(1,1,0)
#3: 0x006e00c8 id=(4,1,0)
#4: 0x006e4458 id=(2,0,0)
#5: 0x00b13718 id=(1,2,0)
#6: 0x006e8868 id=(3,0,0)
#0: 0x006636f8 id=(1,0,0)
#1: 0x00670048 id=(4,0,0)
#2: 0x00663708 id=(1,1,0)
#3: 0x006700c8 id=(4,1,0)
#4: 0x00674458 id=(2,0,0)
#5: 0x00663718 id=(1,2,0)
#6: 0x00678868 id=(3,0,0)
- ASLRによってポインタは毎回違っているが、そのポインタから取得したidは毎回同じになっている。
- だからメモリ上に構造木などを作った場合、そのリンク先のポインタのidを見れば、ポインタがおかしくなっているかどうかや、前に見た時と同じところを指しているのかどうかを簡単に見分けられる。
- そしてこのidは環境に依存しないので、最初はWindows上で開発していたが途中からLinux上で開発しているような場合でも、idに関するメモは全部そのまま使えることになる。