アドレス空間の旅


メモリ確保の方法によって確保される領域の番地に差異が生じるかを検討しました。

// array_address.c
#include<stdio.h> // printf
#include<stdlib.h> // malloc, free
#define LENGTH 3
int main(void)
{

//配列の宣言と同時に、特定の大きさだけ仮想アドレス空間内に確保している。
char array_static_1[LENGTH];
char array_static_2[LENGTH];
char *array_dynamic_ptr_1;
char *array_dynamic_ptr_2;
int i;

/*mallocにより(int型の大きさ)× LENGTHだけの値を与える。
戻り値は、mallcにより確保された領域の先頭のアドレスである/。
*/
array_dynamic_ptr_1 = (char *) malloc (sizeof (char) * LENGTH);
array_dynamic_ptr_2 = (char *) malloc (sizeof (char) * LENGTH);


for(i = 0; i<LENGTH; i++)
printf("array_static_1[%d]=%p\n", i, &array_static_1[i]);
for(i = 0; i<LENGTH; i++)
printf("array_static_2[%d]=%p\n", i, &array_static_2[i]);
for(i = 0; i<LENGTH; i++)
printf("array_dynamic_ptr_1[%d]=%p\n", i, &array_dynamic_ptr_1[i]);
for(i = 0; i<LENGTH; i++)
printf("array_dynamic_ptr_2[%d]=%p\n", i, &array_dynamic_ptr_2[i]);
//確保したメモリ領域を開放。
free(array_dynamic_ptr_1);
free(array_dynamic_ptr_2);

return 0;
}




$ gcc -o array_address array_address.c

$ ./array_address
array_static_1[0]=0xbf8b592d
array_static_1[1]=0xbf8b592e
array_static_1[2]=0xbf8b592f
array_static_2[0]=0xbf8b592a
array_static_2[1]=0xbf8b592b
array_static_2[2]=0xbf8b592c
array_dynamic_ptr_1[0]=0x80dd008
array_dynamic_ptr_1[1]=0x80dd009
array_dynamic_ptr_1[2]=0x80dd00a
array_dynamic_ptr_2[0]=0x80dd018
array_dynamic_ptr_2[1]=0x80dd019
array_dynamic_ptr_2[2]=0x80dd01a


この結果から大変興味深いことがわかります。
それは、mallocで確保される領域の方が、静的に割り当てられる領域の方がアドレス番地が若いことがわかります。そして、同じカテゴリの変数は、連続して割り当てられていることがわかります。

このことを理解するには、仮想アドレス空間の概念を理解する必要があるようです。

UNIXの場合、プログラムが実行されると、各プロセスごとに、
32bitOSの場合、0x00000000-0xffffffff番地までの連続した合計32bit(=4GB)のアドレス空間が割り当てられるとのことです。

もちろん、このアドレス空間というのは仮想メモリのことであり、実メモリとはまったく異なります。OSがリソース管理のために提供するサービスだと考えればよいです。

そして、mallcにより確保される領域は、データ領域とよばれる所であり、それは比較的若い番地が割り当てられています。
一方、静的に確保された領域は、スッタク領域と呼ばれ、比較的大きい番地に割り当てられています。スタック領域は、大きい番地から小さい番地に向けて変数が確保されていくのが特徴的です。