ヒープ領域に割り当てたアドレスでメモリープールを作るのが、筆者が定義するカスタムヒープアロケーターです。
メモリープールとは malloc() で割り当てられたヒープ領域のことで、特に何か変なことはする必要はありません。
しかし都度 malloc() / free() をするスタイルではなく、malloc() も free() も一回だけしか行わないのがポイントです。
考え方としてはカスタムスタックアロケーターと同様で、割り当てたメモリー領域のアドレスを加算したり減算して、どの変数やオブジェクトに使うかの管理は自分でやります。
この場合に重要なのが、ヒープ領域のアドレスが上方向か、下方向に割り当てられていくかという点です。
例えばアドレス領域が 0x10 から 0x20 だと仮定して考えてみてください。
8 バイト間隔のアドレスを使いたい場合は [0x10, 0x18, 0x20] というように上方向か、 [0x20, 0x18, 0x10] の下方向のいずれかの可能性があります。
幸いにもこの検証は容易にできるのでやってみましょう。
main.cpp.
  1 #include <cstdio>
  2 #include <cstdlib>
  3
  4 int main()
  5 {
  6   int *x = new int(5);
  7   int *y = new int(10);
  8   std::printf("x: %p\n",x);
  9   std::printf("y: %p\n",y);
 10
 11   int* arr = new int[10];
 12
 13   for(int i = 0; i < 10; ++i){
 14     std::printf("arr[%d]: %p\n",i,arr+i);
 15   }
 16
 17   delete x;
 18   delete y;
 19   delete[] arr;
 20   return 0;
 21 }
ビルドと実行結果.
$ g++ main.cpp $ ./a.out x: 0x55dc7ad0ee70 y: 0x55dc7ad0ee90 arr[0]: 0x55dc7ad0f2c0 arr[1]: 0x55dc7ad0f2c4 arr[2]: 0x55dc7ad0f2c8 arr[3]: 0x55dc7ad0f2cc arr[4]: 0x55dc7ad0f2d0 arr[5]: 0x55dc7ad0f2d4 arr[6]: 0x55dc7ad0f2d8 arr[7]: 0x55dc7ad0f2dc arr[8]: 0x55dc7ad0f2e0 arr[9]: 0x55dc7ad0f2e4
このソースコードでは new / delete を使ってますが、malloc() / free() でも同じとなるはずです。
まあやりたい人は自分でやってみてくださいね。
それで最初の検証は、割り当ての順序とアドレス割り当ての関係です。
  6   int *x = new int(5);
  7   int *y = new int(10);
  8   std::printf("x: %p\n",x);
  9   std::printf("y: %p\n",y);ポインターは以下のような値となります。
x: 0x55dc7ad0ee70 y: 0x55dc7ad0ee90
y は x の後に割り当てられ、 x のアドレスより上位アドレスにあるので、上方向にアドレスが伸びていってますね。
では配列はどうでしょうかね?
 11   int* arr = new int[10];
 12
 13   for(int i = 0; i < 10; ++i){
 14     std::printf("arr[%d]: %p\n",i,arr+i);
 15   }この場合は arr[] 配列には整数型 10 個分のメモリー割り当てがされてます。
これを要素ごとに出力すると以下のようになります。
arr[0]: 0x55dc7ad0f2c0 arr[1]: 0x55dc7ad0f2c4 arr[2]: 0x55dc7ad0f2c8 arr[3]: 0x55dc7ad0f2cc arr[4]: 0x55dc7ad0f2d0 arr[5]: 0x55dc7ad0f2d4 arr[6]: 0x55dc7ad0f2d8 arr[7]: 0x55dc7ad0f2dc arr[8]: 0x55dc7ad0f2e0 arr[9]: 0x55dc7ad0f2e4
配列のインデックスが上がるほど、アドレスも上位アドレスになっています。
てなことで、ヒープ領域のメモリーは上向きに伸びてくことが確認できました。
Copyright 2018-2019, by Masaki Komatsu