程序的内存空间

kongyijin / 2023-05-07 / 原文

进程的内存空间分布

从下往上分别是:

  • 正文段(代码段).text
     只读,可共享; 代码段(code segment/text segment )通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。
        在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。
  • 数据段

       储存已被初始化了的静态数据。数据段(data segment )通常是指用来存放程序中已初始化的全局变量或者静态变量的一块内存区域。数据段属于静态内存分配。

  • BSS 段
            未初始化的数据段. BSS 段(bss segment )通常是指用来存放程序中未初始化的全局变量或者静态变量的一块内存区域。BSS 是英文Block Started by Symbol 的简称。BSS 段属于静态内存分配。
  • 堆(heap)

     堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc 等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free 等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。

  •  栈(stack)

       栈又称堆栈,是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{} ”中定义的变量(但不包括static 声明的变量,static 意味着在数据段中存放变量)。

       除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/ 恢复调用现场。

       从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

  •  共享区
     图中间在栈和堆之间,有一个共享内存的映射的区域。这个就是共享内存存放的地方。一般共享内存的默认大小是32M。
  • 内核空间
       高地址,一般window2G,  Linux1G
       注意:对于x86(32位系统)而言,实际的用户空间只有2G,所以大小一旦超过2G程序就无法正常运行,但是对于x64(64位系统),大小基本不受限制。
       对于Linux,用户实际空间能达到3G(如上图所示)。
 
 图解堆栈空间分配对应的指针代码:

    int* p1 = new int;     //在堆区开辟一块整型内存空间(0x0001),在栈中创建一个指针p1指向这块内存,指针p1本身地址为0xFF09
   //注意,int* p1开辟的空间大小如果是32位机器,就是4个字节;64位机器就是8个字节。但是new int的内存空间大小都是4个字节。
*p1 = 10;         //上面代码开辟的空间中存放的值为10
int s1 = 11;       //在栈区创建变量s1(0xFF05),值为11 int* p2 = &s1;     //又在栈区创建指针p2(0xFF01),指向s1的内存空间(0xFF05),就是说p2中存放的值是s1的地址0xFF05 *p2 = 12;        //因为指针p2指向s1的内存空间,所以改变的是s1的值