メモリ空間のレイアウト: コードセグメント、データセグメント、スタック、ヒープ、レジスタ

まずコードの一部を見てください。

 #include <stdio.h>
  
  int glob_val;               //global uninitialized
  int glob_val2 = 2;          //global initialized
  //int glob_val5 = 4;
  //int glob_val6 = 4;
  static int glob_val3;       //static global uninitialized
  static int glob_val4 = 1;   //static global initialized
  
  int main(int argc , char *argv[]){
      int auto_val ;          //local uninitialized
      int auto_val2 = 3;      //local initialized
      static int stat_val ;   //static local uninitialized
      static int stat_val2 = 4;   //static local initialized
      char *p = "Hello World!";   //point to constant
  //  register reg_val = 5 ;      //register
  
      printf( "global uninitialized var's addr:"
              " %#08lx\n " , &glob_val );
      printf( "global initialized var's addr:"
              " %#08lx\n " , &glob_val2 );
      printf( "global initialized var's addr:"
              " %#08lx\n " , &glob_val3 );
      printf( "static global initialized var's addr:"
              " %#08lx\n " , &glob_val4 );
  
      printf( "constant value's addr:  %#08lx \n "
              "pointer's addr: %#08lx\n" , p , &p );
  //  printf( "register uninitialized var's addr:"
  //          " %#x\n " , &reg_val );
  
      printf( "local uninitialized var's addr:"
              " %#08lx\n " , &auto_val );
      printf( "local initialized var's addr:"
              " %#08lx\n " , &auto_val2 );
      printf( "static local uninitialized var's addr:"
              " %#08lx\n " , &stat_val );
      printf( "static local initialized var's addr:"
              " %#08lx\n " , &stat_val2 );
     return 0;
  }

出力結果は次のとおりです。

グローバル未初期化変数のアドレス: 0x601058
グローバル初期化変数 アドレス: 0x601040グローバル初期化変数のアドレス: 0x601050静的グローバル初期化変数のアドレス: 0x601044定数値のアドレス: 0x400698ポインターのアドレス: 0x7fff54c 54688ローカル初期化されていない変数'アドレス: 0x7fff54c54680ローカルで初期化された変数のアドレス: 0x7fff54c54684静的で初期化されていない変数のアドレス: 0x601054







静的ローカルで初期化された変数のアドレス: 0x601048

それではAPUE P164の写真を見てみましょう 

上記からわかるように、メモリはいくつかのセグメントに大まかに分割されます。

コード セグメント (テキスト セグメント) : コード セグメント (コード セグメント/テキスト セグメント) は、通常、プログラムの実行コードを格納するために使用されるメモリ領域を指します。領域のこの部分のサイズはプログラムの実行前に決定され、メモリ領域は通常読み取り専用であり、一部のアーキテクチャではコード セグメントを書き込み可能にすることもでき、これによりプログラムの変更が可能になります。コード セグメントには、文字列定数などの読み取り専用の定数変数を含めることもできます。

データ セグメント: データ セグメント (データ セグメント) は通常、プログラム内で初期化されたグローバル変数を格納するために使用されるメモリ領域を指します。データ セグメントは静的メモリ割り当てです。

BSSセグメント: BSSセグメント (bsssegment) は通常、プログラム内で初期化されていないグローバル変数を格納するために使用されるメモリ領域を指します。BSS は、English Block Started by Symbol の略称です。BSS セグメントは静的メモリ割り当てです。

ヒープ ( heap ) : ヒープは、プロセスの実行中に動的に割り当てられるメモリ セグメントを格納するために使用され、そのサイズは固定されておらず、動的に拡張または縮小できます。プロセスが malloc などの関数を呼び出してメモリを割り当てると、新しく割り当てられたメモリがヒープに動的に追加されます (ヒープが拡張されます)。free などの関数によってメモリが解放されると、解放されたメモリはヒープから削除されます (ヒープは拡張されます)。ヒープが削減されます)

スタック (スタック) : スタック (スタックとも呼ばれます) は、プログラムを保存するためにユーザーによって一時的に作成されるローカル変数です。つまり、関数括弧 "{}" で定義された変数です (ただし、静的な変数は含まれません)。宣言された変数、静的とはデータ セグメントの格納変数を意味します)。さらに、関数が呼び出されるとき、そのパラメータも呼び出しプロセスのスタックにプッシュされ、呼び出しの終了後、関数の戻り値もスタックに格納されます。スタックの先入れ先出し機能により、スタックは呼び出しシーンの保存/復元に特に便利です。この意味で、スタックは一時的なデータを保存および交換するためのメモリ領域と考えることができます。

上記のプログラムを実行した結果から、次のことがわかります。

1.機能コードはコードセグメントに格納されます。宣言されたクラスが使用されない場合、コンパイル時に最適化され、そのメンバー関数はコード セグメント領域を占有しません。
グローバル変数または静的変数はデータ セグメントに配置されます。 注: 論理的に言えば、宣言されていないグローバル変数または静的変数は BSS に格納される必要がありますが、結果はそれらが一緒であることを示しています

ローカル変数はスタックに配置され、
new で生成されたオブジェクトはヒープに配置されます。

定数は定数領域に格納され、定数領域のアドレスはデータセグメントのアドレスより下位になります。

CPU寄存器:CPU寄存器,其实就是来控制代码段和数据段的指令及数据读取的地方,当然,CPU也有自己存放数据的地方,那就是通用寄存器里的数据寄存器,通常是EDX寄存器,C语言里有个register,就是把数据放在这个寄存器里,这样读取数据就相当的快了,因为不用去内存找,就省去了寻址和传送数据的时间开销。他还有一些寄存器是用来指示当前代码段的位置、数据段的位置、堆栈段的位置等等(注意这里存放的只是相应的代码或数据在内存中的地址,并不是实际的值,然后根据这个地址,通过地址总线和数据总线,去内存中获取相应的值)不然在执行代码的时候,指令和数据从哪取呢?呵呵。。。他里面还有标志寄存器,用来标识一些状态位,比如标识算术溢出呀等等。。。。。

寄存器是特殊形式的内存,嵌入到处理器内部。

每个进程需要访问内存中属于自身的区域,因此,可将内存划分成小的段,按需分发给进程。
寄存器用来存储和跟踪进程当前维护的段。偏移寄存器(Offset Registers)用来跟踪关键的数据放在段中的位置。在进程被载入内存中时,基本上被分裂成许多小的节(section)。我们比较关注的是6个主要的节:

(1) .text 节
    .text 节基本上相当于二进制可执行文件的.text部分,它包含了完成程序任务的机器指令。
该节标记为只读,如果发生写操作,会造成segmentation fault。在进程最初被加载到内存中开始,该节的大小就被固定。
(2).data 节
.data节用来存储初始化过的变量,如:int a =0 ; 该节的大小在运行时固定的。
(3).bss 节
栈下节(below stack section ,即.bss)用来存储为初始化的变量,如:int a; 该节的大小在运行时固定的。
(4) 堆节
堆节(heap section)用来存储动态分配的变量,位置从内存的低地址向高地址增长。内存的分配和释放通过malloc() 和 free() 函数控制。
(5) 栈节
栈节(stack section)用来跟踪函数调用(可能是递归的),在大多数系统上从内存的高地址向低地址增长。
同时,栈这种增长方式,导致了缓冲区溢出的可能性。
(6)环境/参数节

环境/参数节(environment/arguments section)用来存储系统环境变量的一份复制文件,
进程在运行时可能需要。例如,运行中的进程,可以通过环境变量来访问路径、shell 名称、主机名等信息。
该节是可写的,因此在格式串(format string)和缓冲区溢出(buffer overflow)攻击中都可以使用该节。
另外,命令行参数也保持在该区域中.

 

另外还有一篇文章:http://www.cppblog.com/prayer/archive/2009/08/17/93594.html我去验证BSS和数据段,没有验证成功。

 


おすすめ

転載: blog.csdn.net/big_bit/article/details/51273063