C/C++面试:38---描述一下C/C++的内存分区(内存四区、内存五区)、栈和堆的区别

一、C/C++的内存分区

  • C/C++把内存分为:栈区、堆区、全局区(静态区)、常亮区、代码区
  • 那“内存四区”和“内存五区”有什么区别吗?
    • 其实“内存四区”和“内存五区”指的东西都是完全一样的
    • 内存五区为:栈区、堆区、全局区(静态区)、常亮区、代码区
    • 内存四区为:栈区、堆区、数据区(全局区(静态区)、常亮区)、代码区
    • 因此从上面可以看出,对于内存四区而言,其只是把全局区(静态区)和常亮区合并为一个数据区而已,其实内容都是完全一样的

二、内存五区

栈区

  • 栈区主要存放局部变量、函数调用参数等
  • 栈区由编译器自动分配和释放
  • 栈属于 计算机系统的数据结构,进栈出栈有相应的计算机指令支持,而且分配专门的寄存器 存储栈的地址,效率分高,内存空间是连续的,但栈的内存空间有限

堆区

  • 使用malloc()/new()申请的内容存储在堆区
  • 堆区由程序员手动分配,因此需要自己释放,如果不释放就会产生内存的泄漏
  • 内存空 间几乎没有限制,内存空间不连续,因此会产生内存碎片。操作系统有一个记录空间 内存的链表,当收到内存申请时遍历链表,找到第一个空间大于申请空间的堆节点, 将该节点分配给程序,并将该节点从链表中删除。一般,系统会在该内存空间的首地 址处记录本次分配的内存大小,用于 delete 释放该内存空间

全局区(静态区)

  • 全局区分为两个段:
    • DATA段:存储初始化的全局变量、初始化的静态变量
    • BSS段:存储未初始化的全局变量、未初始化的静态变量
  • 其中BSS段会在程序执行前,将内容全部置为0,所以未初始化的全局变量和未初始化的静态变量的值都为0

常量区

  • 存放常量,而且不允许修改
  • 程序结束之后由系统释放

代码区

  • 主要存放程序中的代码(二进制),属性是只读

三、内存四区

  • 文章最前面已经说过了,内存四区与内存五区的内容是完全一样的,只是其把“全局区(静态区)”和“常量区”合并为一个“数据区”而已
  • 因此,内存四区为:
    • 栈区
    • 堆区
    • 数据区(包含全局区(静态区)和常量区)
    • 代码区

四、代码演示

int a = 0;                //全局初始化区 
char *p1;                 //全局未初始化区

int main(){ 
    int b;                //栈 
    char s[] = "abc";     //栈
    char *p2;             //栈 

    char *p3 = "123456";  //123456\0在常量区,p3在栈上

    static int c = 0;    //全局(静态)初始化区
 
    p1 = (char *)malloc(10); 
    p2 = (char *)malloc(20); //分配得来得10和20字节的区域就在堆区

    strcpy(p1, "123456");    //123456\0放在常量区, 编译器可能会将它与p3所指向的"123456"优化成一块
    return 0;
}

五、栈和堆的区别

  • 存储的内容:
    • 栈存局部变量、函数参数等
    • 堆存储使用 new、malloc 申请 的变量等
  • 申请的方式:
    • 栈内存由系统分配
    • 堆内存由自己申请
  • 申请后系统的响应:
    • 栈——只要栈的剩余空间大于所申请空间,系统将为程序提供 内存,否则将报异常提示栈溢出
    • 堆——首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申 请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空 闲结点链表 中删除,并将该结点的空间分配给程序
  • 申请大小的限制:
    • Windows 下栈的大小一般是 2M,堆的容量较大
  • 申请效率的对比:
    • 栈由系统自动分配,速度较快
    • 堆使用 new、malloc 等分配,较慢

猜你喜欢

转载自blog.csdn.net/qq_41453285/article/details/107744570
今日推荐