【图解八股-C/C++③-内存管理】

作者简介和专栏内容见专栏介绍:https://www.nowcoder.com/creation/manager/columnDetail/0eL5bM

麻烦看到贴子的伙伴点点赞大家点赞订阅支持下,提前祝各位offer多多,有问题评论区见~~

图解版

内存管理

类对象的大小受哪些因素影响?

1) 类的非静态成员变量大小,静态成员不占据类的空间,成员函数也不占据类的空间大小;

2) 内存对齐另外分配的空间大小,类内的数据也是需要进行内存对齐操作的;

3) 虚函数的话,会在类对象插入vptr指针,加上指针大小;

4) 当该该类是某类的派生类,那么派生类继承的基类部分的数据成员也会存在在派生类中的空间中,也会对派生类进行扩展。

空类的大小是多少吗?

1) C++空类的大小不为0,不同编译器设置不一样,vs设置为1;

2) C++标准指出,不允许一个对象(当然包括类对象)的大小为0,不同的对象不能具有相同的地址;

3) 带有虚函数的C++类大小不为1,因为每一个对象会有一个vptr指向虚函数表,具体大小根据指针大小确定;

4) C++中要求对于类的每个实例都必须有独一无二的地址,那么编译器自动为空类分配一个字节大小,这样便保证了每个实例均有独一无二的内存地址。

简要说明C++的内存分区

C++中的内存分区,分别是堆、栈、自由存储区、全局/静态存储区、常量存储区和代码区。如下图所示

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

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

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

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

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

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

堆和栈的区别

先讲讲内存分区,讲底层(下边),再讲具体区别

因为操作系统会在底层对栈提供支持,会分配专门的寄存器存放栈的地址,栈的入栈出栈操作也十分简单,并且有专门的指令执行,所以栈的效率比较高也比较快。

而堆的操作是由C/C++函数库提供的,在分配堆内存的时候需要一定的算法寻找合适大小的内存。并且获取堆的内容需要两次访问,第一次访问指针,第二次根据指针保存的地址访问内存,因此堆比较慢。

  • 申请方式不同
  • 申请大小限制不同
  • 申请效率不同

栈空间默认是4M, 堆区一般是 1G - 4G

堆和栈出现数组越界各自的表现

栈区数组越界:

1:栈区数组越界会将形参或者局部变量丢掉,可能导致函数运行参数取空,进程崩溃。

2:形参或者局部变量是循环停止条件,可能导致死循环。

3:函数调用栈越界,可能将下一条指令跳转地址或者上层函数地址踩,导致命令执行异常,或者访问非法函数地址。

堆区数组越界:

1:堆访问越界,当越界地址没有分配给其他内容,则不会存在明显副作用。已经分配给其他线程使用,则会出现踩内容。同时由于堆分配的内存,实际会比malloc的大,在踩内存是不一定会踩到其他变量或者线程的空间

什么是内存泄露,如何检测与避免

内存泄露

一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定)内存块,使用完后必须显式释放的内存。应用程序般使用malloc,、realloc、new等函数从堆中分配到块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了

后果

只发生一次小的内存泄漏可能不被注意,但泄漏大量内存的程序将会出现各种证照:性能下降到内存逐

渐用完,导致另一个程序失败;

避免内存泄露的几种方式

  • 计数法:使用new或者malloc时,让该数+1,delete或free时,该数-1,程序执行完打印这个计数,如果不为0则表示存在内存泄露 (智能指针)
  • 一定要将基类的析构函数声明为虚函数
  • 对象数组的释放一定要用delete []
  • 有new就有delete,有malloc就有free,保证它们一定成对出现

如何排除

使用工具软件BoundsChecker,BoundsChecker是一个运行时错误检测工具,它主要定位程序运行时期发生的各种错误;

调试运行DEBUG版程序,运用以下技术:CRT(C run-time libraries)、运行时函数调用堆栈、内存泄漏时提示的内存分配序号(集成开发环境OUTPUT窗口),综合分析内存泄漏的原因,排除内存泄漏。

什么是内存池,如何实现

内存池(Memory Pool)

是一种内存分配方式。通常我们习惯直接使用new、malloc 等申请内存,这样做的缺点在于:由于所申请内存块的大小不定,当频繁使用时会造成大量的内存碎片并进而降低性能。内存池则是在真正使用内存之前,先申请分配一定数量的、大小相等(一般情况下)的内存块留作备用。当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存。这样做的一个显著优点是尽量避免了内存碎片,使得内存分配效率得到提升。

allocate 包装 malloc,deallocate包装free

一般是一次20*2个的申请,先用一半,留着一半,为什么也没个说法,侯捷在STL那边书里说好像是C++委员会成员认为20是个比较好的数字,既不大也不小。

1. 首先客户端

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

计算机实习秋招全阶段指南 文章被收录于专栏

作者简介:2个月时间逆袭嵌入式开发,拿下理想汽车-ssp、小米汽车-sp、oppo-sp、迈瑞医疗、三星电子等八家制造业大厂offer~ 专栏内容:涵盖算法、八股、项目、简历等前期准备的详细笔记和模板、面试前中后的各种注意事项以及后期谈薪、选offer等技巧。保姆级全阶段教程帮你获得信息差,早日收到理想offer~

全部评论

相关推荐

部门经理1、简单确认情况后,让我进行自我介绍2、说一下C语言内存分配的方式以及区别3、阐述一下C语言程序编译的过程4、static关键字和extern关键字的作用5、静态全局变量和静态局部变量的区别,作用域有什么不同?6、static的全局变量能不能被其他.c文件调用?7、看我简历里面写了熟悉串行通信,让我阐述一下IIC总线和SPI总线的区别8、假如IIC协议中地址位为8bit,那么最多可以挂载多少个从设备?为什么要减1?9、阐述一下实习或者项目过程中遇到的困难10、我投的岗位有加班情况,问我如何看待工作加班?HR提问1、英语四级是大几通过的?2、英语六级呢?3、看我实习经历是在大四上学期进行的,问我实习是自己找的还是老师推荐的?【自己找的】4、为什么这份实习工作不选择留下来?5、我主要从交通极其不方便这方面进行阐述的,但我额外提到了“转正后福利待遇不符合期望”这一点,HR就问了我最低的期望薪资6、看我绩点和英语六级成绩都很好,问我为啥没去考研?7、让我对自己进行一下自我评价,我说到了“学习能力强”这一点,HR就让我举例具体说8、看到我是在寝室进行面试的,就问了我室友找工作的状况9、实习过程中有没有工作失误,具体是怎么进行解决的?10、实习期间还有去投过其他公司吗?11、反问#通信硬件人笔面经互助##传音##春招##校招##驱动开发#
点赞 评论 收藏
转发
1 4 评论
分享
牛客网
牛客企业服务