第91章 ヒープ領域のアドレス

 ヒープ領域に割り当てたアドレスでメモリープールを作るのが、筆者が定義するカスタムヒープアロケーターです。

 メモリープールとは 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