C/C++面试:请描述C/C++程序的内存分区

1059 篇文章 286 订阅

请描述C/C++程序的内存分区

其实c和c卄的内存分区还是有一定区别的,但此处不作区分:

(1)栈区(stack)

  • 由编译器进行管理,在需要时由编译器自动分配空间,在不需要时自动回收空间,一般保存的是局部变量和函数参数等。
  • 一般来说,CPU有专门的指令可以用于入栈和出栈的操作。当一个函数被调用时,就会有指令把当前指令的地址压入栈内保存起来,然后跳转到被调用的函数执行。函数返回的时候,就会把栈里面的指令地址弹出来继续执行。
  • 它是连续的内存空间,在函数调用的时候,首先入栈的是下一条可以执行指令的地址,然后是函数逇各个参数
  • 大多数编译器中,参数是从右向左入栈(原因在于采用这种顺序,可以让程序员在使用C/C++的“函数参数长度可变”这个特性时更方便。如果从左向右压栈,第一个参数(即描述可变参数表各个变量的那个参数)将被放在栈底,由于可变参数函数的第一步就需要解析可变参数表的各个参数类型,即第⼀步就需要得到上述参数,因此,将它放在栈底是很不⽅便的。)
  • 本地函数调用结束时,局部变量先出栈,然后是参数,最后是栈顶指针最开始存放的地址,程序由该点继续运行,不会产生碎片
  • 栈是⾼地址向低地址扩展,栈低⾼地址,空间较⼩。
  • 栈操作很快:
    • 数据存取的位置总是在栈顶而不需要寻找位置存放获取读取数据
    • 栈中的所有数据必须占用已知且固定的大小
    • 调用函数时,传递给函数的值[包括指向对上数据的指针]和函数的局部变量被压入栈中。

(2)堆区(heap):

  • 由程序员管理,需要⼿动 new malloc delete free 进⾏分配和回收,如果不进⾏回收的话,会造成内存泄漏的问题。
  • 在编译时大小未知或者大小可能变化的数据,要存储到堆上
  • 堆是为动态分配预留的内存空间,是不连续的,每个线程都有一个栈,但是每一个应用程序只有一个堆。
  • 堆是缺乏组织的:当向堆放入数据时,需要请求一定大小的空间。操作系统在堆的某处找到一块足够大的空位,把它标记为已使用,并且返回一个表示该位置地址的指针。这个过程称为在堆上分配内存
  • 返回的堆地址指针存放在栈中[因为指针的大小是已知并且固定的]
  • 实际上系统中有一个空闲链表,当有程序申请的时候,系统遍历空闲链表找到第一个大于等于申请大小的空间分配给程序,一般在分配程序的时候,也会在空间头部写入内存大小,方便delete回收空间大小。当然,如果有剩余的,也会将剩余的插入到空闲链表中,这也是产生内存碎片的原因
  • 堆是低地址向⾼地址扩展,空间交⼤,较为灵活。
  • 访问堆上的数据比访问栈上的数据慢:
    • 因为必须通过指针来访问。现代CPU在内存中跳转越少就越快
    • 在堆上分配大量的空间也可能消耗时间
  • 注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。

(3) 全局/静态存储区:分为初始化和非初始化两个相邻区域,存储初始化和未初始化的全局变量和静态变量,程序结束后由系统释放
(4)常量存储区:存储常量,比如字符串,一般不允许修改。程序结束后由系统释放
(5)代码区:存放程序的二进制代码

栈区与堆区的区别:

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

总结:栈区优势在于处理效率,堆区优势在于灵活

内存模型:自由区、静态区、动态区

根据C/C++对象生命周期的不同,C/C++的内存模型有三种不同的内存区域,即:自由存储区、动态区、静态区

  • 自由存储区:局部非静态变量的存储区,也就是平时说的栈
  • 动态区:由new、malloc分配的内存,即平常所说的堆;
  • 静态区:全局变量、静态变量、字符串常量存在的位置

注意:代码虽然占内存,但不属于C/C++内存模型的一部分;

C++是怎么定义常量的?常量存放在内存的哪个位置

  • 对于局部常量,存放在栈区
  • 对于全局常量,编译器一般不分配内存,放在符号表中以提高访问效率
  • 对于字面值常量,比如字符串,一般常在常量区
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值