zoukankan      html  css  js  c++  java
  • 语言基础(5):程序内存结构

    1、C++进程内存分布

    在C/C++程序进程内存分为:代码区、静态区、常量区、堆区、栈区,不同区域存放不同内容:

    内存区 存放内容 说明
    代码区 二进制代码 CPU可执行的机器指令,且是只读的
    静态区 全局和静态变量 包括局部静态变量
    常量区 程序在运行的期间不能够被改变的量 例如: 全局const修饰的变量,字符串常量”abcde”, 数组的名字等
    堆区 存放malloc()函数申请的内存 忘记free()会造成内存泄露,程序结束由系统回收
    new申请的内存可能在这个区域,取决于new的实现
    栈区 存放局部变量 函数内的局部变量、形参和函数返回值,超出数据作用域,被系统回收

    几点需要注意:

    • 代码区,不仅存放程序二进制代码,还包括程序中使用的立即数,例如程序中直接出现的数值,int a = 10;// 10就是立即数;
    • 静态区(static), 全局变量和静态变量存放区(RW),内存中,初始化的全局和静态变量在一块区域,未初始化的全局变量和静态变量在相邻的另一块区域(ZI:ZeroInit);
    • 常量区,常变量和字符串常量、变量名等(RO:ReadOnly);

    程序需要在计算机硬件上运行起来,其实质就是静态可执行的文件加载到内存中的过程,可执行程序文件只是一个程序的载体,程序运行最终要在内存中进行。

    所谓动和静就是指内存分配方式,程序被加载到内存中:

    • 静态分配内存:是在程序编译和链接时就确定好的内存;
    • 动态分配内存:是在程序加载、调入、执行的时候分配/回收的内存;
    int a = 0;     // 静态区-初始化区
    char *p1;    // 静态区-未初始化区(ZI) 
     
    void main() 
    { 
        int b;    // 栈区 
        char s[] = "abc";     // "abc"在常量区,s在栈区。 
        char *p2;     // 栈 
        char *p3 = "123456";     // "123456", 在常量区,p3在栈区。 
        static int c =0;    // 全局(静态)初始化区
        
       /*   p1,p2存放在栈区,存放 malloc 内存的首地址
       *    分配得来得10和20字节的区域就在堆区。      */
        p1 = (char *)malloc(10); 
        p2 = (char *)malloc(20); 
        
        strcpy(p1, "123456");     // "123456" 放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 
    }
    

    #2、可执行文件结构 可执行文件,以windows为例,后缀格式为 .exe (文件结构是PE格式,linux可执行文件没有格式后缀,文件是ELF格式)文件,它可以加载到内存中,并由操作系统加载程序执行,是可在操作系统存储空间中浮动定位的可执行程序。
    ##2.1 可执行文件结构 通过dumpbin(win)、objdump(linux)可以查看可执行文件结构: - .text: 也称为代码段(Code),用来存放程序执行代码,同时也可能会包含一些常量(如一些字符串常量、立即数等),该段内存为静态分配,读写方式 RO(某些架构可能允许修改)。 这块内存是共享的,当有多个相同进程(Process)存在时,共用同一个 .text 段。 - .data: 也有的地方叫GVAR(global value),用来存放程序中已经初始化的非零全局变量。静态分配。.data又可分为读写(RW)区域和只读(RO)区域。  - RW段 则是普通非常全局变量,也包括静态变量; - RO段 保存常量所以也被称为 .constdata (linux中是独立的段 .rodata); - .bss 存放程序中为初始化的和零值全局变量,文件中并不分配存储空间,只记录变量空间大小。静态分配,在程序加载时通常会被清零(所以也叫ZI),读写方式 RW。 - stack: 栈,存放Automatic Variables,按内存地址由高到低方向生长,其最大大小由编译时确定,速度快,但自由性差,最大空间不大,很明显该区域是 RW。 - heap: 堆,自由申请的空间,按内存地址由低到高方向生长,其大小由系统内存/虚拟内存上限决定,速度较慢,但自由性大,可用空间大。(每个线程都会有自己的栈,但是堆空间是共用的),该区域RW。

    进程空间结构内存映射结构

    2.2 可执行文件和进程对应关系

    一个程序需要运行起来,除了映射加载到内存中,还需要更多的空间,完成数据间的交互,否则这个程序就是死的。所以我们还需要为更多的数据和数据交互提供一块内存 —— 堆栈。

    • 栈(stack)
      该段对应进程栈区,用于编译期间就能确定存储大小的存储区,主要用于在函数作用域内创建,离开作用域后自动销毁的变量。也即用于局部变量、函数参数等。栈的存储空间是连续的,两个紧挨着定义的局部变量,他们的存储空间也是紧挨着的。栈是向低地址扩展的数据结构,工作方式和数据结构中的栈类似。栈的大小是有限的,VC++编译器的默认栈的大小为1MB,所以不要定义int a[1000000]这样的超大数组,否则就会发生栈溢出(stack overflow)问题。

    • 堆(heap)
      该段进程堆区,用于编译期间不能确定存储大小的变量的存储区,运行期间确定,它的存储空间是不连续的,一般由malloc(可能 new)函数来分配内存块,并且需要用free(delete)函数释放内存。如果没有释放,就会出现内存泄漏(memory leak)问题。堆是向高地址扩展的数据结构,工作方式和数据结构中的链表类似,所以会产生内存碎片。堆的大小受OS虚拟内存大小限制,理论上每个程序最大可达4GB。

    • .data
      该段对应进程分配存储的变量和常量

      • .data(RW)
        映射进程全局/静态区,用于编译期间就能确定存储大小的变量的存储区,但它用于在整个程序运行期间都可见的全局变量和静态变量(全局的、局部的)。
      • .data(RO)/.constdata
        映射进程常量区,和“全局/静态存储区”一样,用于编译期间就能确定存储大小的常量的存储区,并且在程序运行期间,存储区内的常量是全局可见的,这是一块比较特殊的存储去,他们里面存放的是常量,不允许被修改。
      • .bss
        该段同样映射进程全局/静态区,主要对应未初始化全局变量,紧邻.data(RW)内存空间,在编译期间就能确定存储大小,但是可执行文件中不分配存储,程序加载时进程分配内存;

    注意:

    1. 堆向高内存地址生长;
    2. 栈向低内存地址生长;
    3. 堆和栈相向而生,堆和栈之间有个临界点,称为stkbrk。

    3、程序进程映射示例

    3.1 进程内存映射实例

    假设有如下一段程序

    int main(...) {
        fun_1(...);
        fun_2(...);
        fun_3(...);
        return 0;
    }
    

    那么对应的内存映射结构如下所示:
    代码内存映射

    3.2 函数帧栈

    一个函数被调用时所建立的栈帧包含下面的信息:

    • 被调函数的返回地址。返回地址是存放在被调用函数的栈帧里,还是主调函数的栈帧,取决于不同系统的实现;
    • 主调函数的栈帧信息, 即栈顶和栈底;
    • 为被调用函数的参数分配的空间(win 由右至左入栈,取决于不同系统的实现);
    • 为函数的局部变量分配的栈空间。

    3.3 linux 对象文件结构实例(和win类似)


    #reference [C/C++程序内存的各种变量存储区域和各个区域详解](https://blog.csdn.net/jirryzhang/article/details/79518408) [操作系统执行可执行程序时,内存分配是怎样的](http://nvzhuang.ping-jia.net/jieshao-758155935643838964.htm) [详细的可执行程序结构参考](https://blog.csdn.net/edonlii/article/details/8779075) [C/C++内存分配](https://www.cnblogs.com/yongdaimi/p/6495182.html) [heap 和 free store区别](https://www.cnblogs.com/QG-whz/p/5060894.html)
  • 相关阅读:
    .Net需要掌握的知识
    图片轮播
    vector
    2016ACM青岛区域赛题解
    总是有一个程序的bug没找到
    poj1001_Exponentiation_java高精度
    poj2236_并查集_Wireless Network
    poj1703_Find them, Catch them_并查集
    poj2492_A Bug's Life_并查集
    poj1182食物链_并查集_挑战程序设计竞赛例题
  • 原文地址:https://www.cnblogs.com/wnwin/p/10700196.html
Copyright © 2011-2022 走看看