秋招面经总结—C++内存管理

2、C++内存管理

2.1、内存分区

秋招面经总结—C++内存管理_第1张图片

​ 原文链接:C/C++内存管理详解 | ShinChan’s Blog (chenqx.github.io)

:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限

:就是那些由 new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个 delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收

自由存储区:如果说堆是操作系统维护的一块内存,那么自由存储区就是C++中通过new和delete动态分配和释放对象的抽象概念。需要注意的是,自由存储区和堆比较像,但不等价。

全局**/**静态存储区:全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量和静态变量又分为初始化的和未初始化的,在C++里面没有这个区分了,它们共同占用同一块内存区,在该区定义的变量若没有初始化,则会被自动初始化,例如int型变量自动初始为0

常量存储区:这是一块比较特殊的存储区,这里面存放的是常量,不允许修改

代码区:存放函数体的二进制代码

2.2、堆和栈
1、堆与栈的区别
管理方式 堆中资源由程序员分配,速度慢,有碎片 栈由系统分配,速度快,不会存在碎片
内存管理机制 系统有一个记录空闲内存地址的链表,当系统收到程序申请时,遍历该链表,寻找第一个空间大于申请空间的堆结点,删除空闲结点链表中的该结点,并将该结点空间分配给程序 只要栈的剩余空间大于所申请空间,系统为程序提供内存,否则,异常:栈溢出
空间大小 堆是不连续的内存区域(系统用链表来存储空闲内存地址,不连续),堆大小受限于计算机系统中的有效的虚拟内存(32位 -> 4G),堆内存空间灵活,空间大 栈是一块连续的内存区域,大小由操作系统设置,windows下一般2M。可以通过ulimit -a查看,由ulimit -s修改
碎片问题 堆中要频繁new / delete 会造成大量碎片,使程序效率降低 对于栈,它是有点类似于数据结构上的一个先进后出的栈,进出一一对应,不会产生碎片。
生长方向 堆向上,向高地址方向增长 栈向下,向低地址方向增长
分配方式 堆都是动态分配(没有静态分配的堆) 栈有静态分配和动态分配,静态分配由编译器完成(如局部变量分配),动态分配由alloca函数分配(编译器释放)
分配效率 堆由C/C++函数库提供,机制很复杂。在分配堆内存的时候需要一定的算法寻找合适大小的内存,并且获取堆的内容需要两次访问,第一次访问指针,第二次根据指针保存的地址访问内存,因此堆比较慢。 栈是其系统提供的数据结构,计算机载底层对栈提供支持,分配专门寄存器存放栈地址,栈操作有专门的指令,且入栈和出栈比较简单。
2、为什么栈的速度比堆快?底层如何实现的?
  • 申请速度快:栈是程序运行前就已经分配好的空间,所以运行时分配几乎不需要时间。而堆是运行时malloc动态申请的 ,调用brk/sbrk 系统调用函数控制堆顶_edata往高地址方向变化,相当于将分配内存的耗时由编译阶段转嫁到了机器运行阶段,将分配过程从编译器搬到了运行的代码中。于是动态分配的速度不仅与分配算法有关,还与机器运行速度有关。 且malloc还需要动态的回收垃圾空间,一定程度上影响运行速度。

    • (栈是编译时分配空间,而堆是动态分配(运行时分配空间),所以栈的申请速度快)
  • 存储寻址速度快:栈的物理地址空间是连续的,而堆未必,查找堆的链表也会耗费较多时间,所以存储寻址速度慢。

  • CPU硬件操作速度快:cpu有专门的寄存器(rsprbp)来操作栈,堆是使用间接寻址的,所以栈快。

  • 硬件支持不同:栈是在一级缓存中做缓存的, 而堆则是在二级缓存中, 两者在硬件性能上差异巨大

    原文链接:https://blog.csdn.net/h2517956473/article/details/115317689

3、为什么不能多使用栈?

栈的地址空间必须连续,如果任其任意成长,会给内存管理带来困难。对于多线程程序来说,每个线程都必须分配一个栈,因此没办法让默认值太大。

4、栈的底层原理:汇编?
秋招面经总结—C++内存管理_第2张图片
//举个栗子:实现两个数相加
int my_add(int a, int b)
{
	int z = a + b;
	return z;
}
 
int main()
{
	int a = 0XAAAAAAAA;
	int b = 0xFFFFFFFF;
	int add = my_add(a,b);
	cout << add << endl;
	return 0;
}
秋招面经总结—C++内存管理_第3张图片
1)栈帧

​ 机器用栈来传递过程参数、存储返回信息、保存寄存器用于以后恢复,以及本地存储。而为单个过程分配的那部分栈称为帧栈;帧栈可以认为是程序栈的一段,它有两个端点,一个标识起始地址,一个标识着结束地址,两个指针结束地址指针esp,开始地址指针ebp;

2)指针移动

​ 由一系列栈帧构成,这些栈帧对应一个过程,而且每一个栈指针+4的位置存储函数返回地址;每一个栈帧都建立在调用者的下方,当被调用者执行完毕时,这一段栈帧会被释放。由于栈帧是向地址递减的方向延伸,因此如果我们将栈指针减去一定的值,就相当于给栈帧分配了一定空间的内存。如果将栈指针加上一定的值,也就是向上移动,那么就相当于压缩了栈帧的长度,也就是说内存被释放了。

3)函数调用过程实现
  • 备份原来的帧指针,调整当前的栈帧指针到栈指针位置;
  • 建立起来的栈帧就是为被调用者准备的,当被调用者使用栈帧时,需要给临时变量分配预留内存;
  • 使用建立好的栈帧,比如读

你可能感兴趣的:(c++)