C/C++内存管理讲解

在这里插入图片描述

在这里插入图片描述

c/C++内存管理讲解

在这里插入图片描述

在这里插入图片描述

1、C/C++内存分布

首先通过一些题目的引入讲解带大家走进C/C++的内存分布。

在这里插入图片描述

eg1:
根据上述变量的定义,来判断它们所在的内存位置。
从接下来的4个选项中选出最佳答案填入(注:可重复选)。

A、栈
B、堆
C、数据段
D、代码段

(1)shelter 在哪里?____;

(2)endanger 在哪里?____;

(3)stake 在哪里?____;

(4)substitute 在哪里?____;

(5)transfer 在哪里?____;

(6)federal 在哪里?____;

(7)*federal 在哪里?____;

(8)export 在哪里?____;

(9)*export 在哪里?____;

(10)slip 在哪里?____;

(11)*slip 在哪里?____。

eg2:
算出上述部分变量的大小或者长度。(以32位平台下的程序为标准)

(1)sizeof(transfer) = ____;

(2)sizeof(federal) = ____;

(3)strlen(federal) = ____;

(4)sizeof(export) = ____;

(5)strlen(export) = ____;

(6)sizeof(slip) = ____;

附:

C/C++中程序内存区域划分图

在这里插入图片描述

说明:

① 栈又叫堆栈,用来存放非静态局部变量、函数参数以及返回值等等。(栈是向下增长的)

② 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享内存,做进程间通信。

③ 堆用于程序运行时动态内存分配。(堆是可以向上增长的)

④ 数据段是用于存储全局数据和静态数据段。

⑤ 代码段是用于存储可执行的代码或者只读常量这些的。

给了点提示,接下来xdm就只需要认真思考下,我这里插播几张图作为缓冲区后再公布答案。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

正确答案:

第一题:
(1)~(5):C C C A A
(6)~(11):A A A D A B

第二题:
(1):40;
(2):5;
(3):4;
(4):4;
(5):4;
(6):4;

不出意外的话,像我这样子的水货肯定是全错,像xdm这样子的水平肯定是全对了。

在这里插入图片描述

答案解析:

第一题:

(1)~(5)这部分可能存在疑惑的就是第三题这个变量明明是定义在局部为什么不是在栈区而是在数据段上面,出现这个问题的极大概率可能是忘记了static关键字的作用,使其被修饰的变量变成静态变量,所以在内存中的位置是在数据段。不过我觉得大部分的xdm选错肯定是因为手抖了。

在这里插入图片描述

(6)~(11)这部分问题较大的应该会是第七题,(*federal)为什么是在栈上而不是在数据段上,原因在于federal是在栈上开辟了五个byte的空间把字符串拷贝进去(别忘记有\0的存在),因此(*federal)不是常量字符串,而是在栈上开辟的临时空间。其次有问题的可能会是第九题,要记住字符串是常量,放在数据段上面的。然后第十一题是通过malloc函数动态向内存堆中申请开辟空间,这个没什么好解释的,选错的xdm肯定是手抖或者眼花了。

在这里插入图片描述

第二题:

附:
由于这个题是以32位平台下为标准的,所以指针大小是4;如果是64位平台下,指针的大小就是8而不是4。

(1)~(6)这部分可能有问题会是第一题,因为是指定开辟10个int类型大小的数组空间,所以是40个字节。其次是第二、三题这样子的,记住sizeof算空间的时候,会把\0算进去,但是strlen算字符长度的时候,遇到\0就终止,所以答案是5和4。像我就经常搞混,以xdm的机智肯定是分分钟秒杀这种小题。

在这里插入图片描述

2、C语言中动态内存管理的方式

在C语言中,主要的动态内存管理方式就是:
malloc/calloc/realloc 和 free

还是用题的方式带xdm回顾下C语言的动态内存管理方式。

题目代码如下:

在这里插入图片描述

问题一:malloc/calloc/realloc的区别是什么?
问题二:这里需要free(p2)吗?

附:

MSDN下这些函数的解析:

malloc

在这里插入图片描述

calloc

在这里插入图片描述

realloc

在这里插入图片描述

楼主的英语也不好,但是通过日积月累的学习也是能看懂这上面的函数介绍,我觉得兄弟们看懂肯定也是绰绰有余,提示已经给了,接下来还是插播几张图后公布答案。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

答案解析:

题一:

① malloc是随机地向堆区动态申请开辟内存空间,不会将开辟好的内存空间初始化;

② calloc则是在malloc的基础上,并将这些开辟好的内存空间都按字节序列初始化为0,通俗易懂理解就是初始化以后都是指向空指针。calloc的作用就相当于malloc配合着memset一起使用(即calloc = malloc + memset);

③ realloc比较特殊,它是向编译器申请开辟一片连续空间区域的扩容,而不同于malloc和calloc那样随机申请位置扩容。(即realloc是不会间断的一片空间区域,而malloc和calloc是能允许间断的空间区域)
编译器会根据其具体的情况选择进行原地扩容还是异地扩容,当你用realloc原先申请的那一块区域不足以满足你当前内存需求时,编译器就会采用异地扩容的方式,将原先那块内存空间的数据拷贝过去到一个新的足够大的空间里去。(realloc通常在写数据结构中的顺序表的时候常用)

为了加深xdm的印象,我再图示给你看。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

题二:

基于题一理解的基础之上,我们就能知道这里是可以不需要free(p2)的,因为这块连续的空间并未使用,而用calloc申请开辟的内存空间默认都会按字节序列初始化为0,即指向的都是空指针。

不出意外的话,以xdm的水准肯定又是狠狠拿下!

在这里插入图片描述

3、C++中动态内存管理的方式

前言:C语言的内存管理方式在C++中仍然还是可以继续使用的,只是有些地方就无能为力而且使用起来比较麻烦(在自定义类型这方面尤其明显,接下来会详细介绍)。对此,C++在C语言的基础之上又诞生出了自己的内存管理方式——通过new和delete操作符进行动态内存管理。

切记:new和delete是操作符而不是像C语言那样动态开辟是库函数。

在这里插入图片描述

(1)new和delete操作内置类型

在这里插入图片描述

注意:申请和释放单个元素的空间,配合使用的是new和delete操作符;申请和释放连续的空间,配合使用的是new[]和delete[]。

需谨记搭配使用不要搞混,不然编译器可能就会出现报错,毕竟这本身就是错误的写法,“常在河边走,哪有不湿鞋!” 如果编译器不报错,不要抱有侥幸心理认为自己就是对的。

在这里插入图片描述

(2)new和delete操作自定义类型

在这里插入图片描述

在这里插入图片描述

注意:在申请自定义类型的内存空间时,C++中的new会调用构造函数,delete会调用析构函数;而C语言中的malloc与free这样子的是都不会调用的。

在这里插入图片描述

附:
拓展内容:

C++提出new和delete操作符用于管理内存主要是用来解决两个问题:

① 对于自定义类型对象自动申请的时候,初始化和清理的问题。(new/delete)会自动调用构造函数和析构函数。

② new失败了以后要求抛异常处理,这样才能符合面向对象语言出错的处理机制。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

注:delete和free一般是不会释放内存空间失败的,若失败了,通常都是由于释放空间上存在越界或者释放的指针位置不对。

在这里插入图片描述

4、operator new 与 operator delete 函数

(1)operator new 与 operator delete函数

简介:new 和 delete 是用户进行动态内存申请和释放的操作符,operator new 和 operator delete 是系统提供的全局函数,new 在底层调用 operator new 全局函数来申请空间,delete 在底层通过 operator delete 全局函数来释放空间。

具体需要通过观察底层原理的方式来进一步理解,这对于我们初学者太过于深入,容易把简单的问题复杂化,因此这边是直接给结论。

即:operator new 实际也是通过 malloc 来申请空间,如果 malloc 申请空间成功就直接返回,否则执行用户提供的空间不足应对措施;如果用户提供该措施就继续申请,否则就抛异常。operator delete 最终是通过free来释放空间的。

通俗易懂地理解就是 operator new 和 operator delete 就是对 malloc 和 free 封装。
ooperator new 中调用 malloc 申请内存,若失败以后,就会改为抛异常处理错误,这样就很符合C++面向对象语言错误的处理方式。

在这里插入图片描述

(2)operator new 与 operator delete 的类专属重载

下面代码演示了,针对链表的节点ListNode通过重载类专属 operator new /operator delete,实现链表节点使用内存池申请和释放内存,提供效率。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

其实内存池就是所谓的池化技术,何为池化技术呢?用个比较通俗易懂的例子方便大家理解,大家从小就应该听过一个和尚挑水喝、两个和尚抬水喝、三个和尚没水喝的故事吧!和尚们只能通过下山挑水才能有水喝,而且一次还只能挑一桶,非常费时费力;而若直接能在居住的寺庙旁建个水井的话,就能非常轻松挑水喝了,池化技术正是如此!

在这里插入图片描述

5、new 和 delete 的实现原理

(1)内置类型

若申请的是内置类型的空间,new 和 malloc,delete 和 free 基本类似,不同的地方是:new 和 delete 申请和释放的是单个元素的空间,new[] 和 delete[] 申请的是连续空间,而且 new 在申请空间失败时会抛异常,而 malloc 是会返回NULL。

(2)自定义类型

new 的原理:

① 调用 operator new 函数申请空间。

② 在申请的空间上执行构造函数,完成对象的构造。

delete 的原理:

① 在空间上执行析构函数,完成对象中资源的清理工作。

② 调用operator delete函数释放对象的空间。

new T[N] 的原理:

① 在空间上执行析构函数,完成对象中资源的清理工作。

② 调用 operator delete 函数释放对象的空间。

delete[] 的原理

① 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理。

② 调用 operator delete[] 释放空间,实际在 operator delete[] 中调用 operator delete 来释放空间。

6、定位 new 表达式(placement-new)

① 概述:定位 new 表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。

② 使用格式:
new(place_address)type 或者 new(place_address)type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表

③ 使用场景:
定位 new 表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用 new 的定义表达式进行显示调析构造函数进行初始化。

代码演示讲解:

在这里插入图片描述

在这里插入图片描述

7、内存管理的相关总结

(1)malloc / free 和 new / delete 的区别:(从用法上和底层上分析下手)

malloc / free 和 new / delete 的共同点是:都是从堆上申请空间,并且需要用户手动释放。

不同点是:

① malloc 和 free 是函数,new 和 delete 是操作符。

② malloc 申请的空间不会初始化,而 new 是可以初始化的。

③ malloc 申请空间时,需要手动计算空间大小并传递,而 new 只需要在其后跟上空间的类型即可。

④ malloc 的返回值为 void*,在使用时必须强转,new 不需要,因为 new 后跟的是空间的类型。

⑤ malloc 申请空间失败时,返回的是NULL,因此使用时必须判空;而 new 不需要,但是 new 需要捕获异常。

⑥ 申请自定义类型对象时,malloc / free 只会开辟空间,不会调用构造函数与析构函数,而 new 在申请空间后会调用构造函数完成对象的初始化,delete 会在释放空间前调用析构函数完成空间中资源的清理。

(2)内存泄露:

① 什么是内存泄漏?② 内存泄露的危害是什么?

① 内存泄漏的定义:内存泄漏是指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。

② 内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,比如操作系统、后台服务等等,若一直出现内存泄漏并未及时处理,就会导致响应越来越慢,最终卡死。

在这里插入图片描述

代码演示讲解内存泄漏:

在这里插入图片描述

③ 内存泄漏的分类:

在这里插入图片描述

C/C++程序中一般我们关心两种方面的内存泄漏:

【1】堆内存泄漏(Heap leak)

堆内存指的是程序执行中依据需要分配通过 malloc / calloc / realloc / new 等从堆中分配的一块内存,用完后必须通过调用相应的 free 或者 delete 删掉。假设程序的设计错误导致这部分内存没有被释放,那么以后这部分空间将无法再被使用,就会产生堆内存泄漏(Heap leak)。

【2】系统资源泄漏

指的是程序使用系统分配的资源,比如套接字、文件描述符、管道等没有使用对应的函数释放掉,导致系统资源的浪费,严重可导致系统效能减少,系统执行不稳定。

④ 如何避免内存泄漏?

【1】工程前期良好的设计规范,养成良好的编码规范,申请的内存空间记着匹配的去释放。ps:这个是理想状态。但是如果碰上抛异常时,就算注意释放了,还是可能会出现问题。这就需要下一条智能指针来管理才有保证。

【2】采用RAII思想或者智能指针来管理资源。

【3】有些公司内部规范使用内部实现的私有内存管理库。这套库自带内存泄漏检测的功能选项。

【4】出问题了使用内存泄漏的工具检测。ps:不过很多工具是不靠谱的,或者收费比较昂贵。

在这里插入图片描述

备注:

C/C++内存管理讲解就此完结,楼主不才,不喜勿喷,若有错误或需要改进的地方,非常感谢你的指出,我会积极学习采纳。谢谢家人们一直以来的支持和鼓励,我会继续努力再接再励创作出更多优质的文章来回报家人们的。编程爱好的xdm,若有编程学习方面的问题可以私信我一同探讨(我尽力帮),毕竟“众人拾柴火焰高”,大家一起交流学习,共同进步!

在这里插入图片描述

2023年3月11日

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 《C/C++程序员面试宝典》是一本针对C/C++程序员面试准备的宝典。这本书的作者通过总结面试过程中常见的问题和经验,帮助读者提高面试技巧和应对能力。 首先,本书中提供了大量的面试题目,内容涵盖了C/C++语言的各个方面,包括数据结构、算法、指针、内存管理、多线程等。通过学习这些题目,读者可以加深对C/C++的理解,提高解决问题的能力。 其次,本书还针对不同类型的面试问题提供了详细的解答思路和讲解。这些解答思路不仅能帮助读者快速解答面试问题,还能帮助读者理解背后的原理和思想,从而更好地运用到实际开发中。 此外,本书还提供了面试中常见的技术知识点总结,帮助读者快速复习和掌握重要的概念和原理。同时,还包含了一些实际项目中常见的问题和解决方案,帮助读者在面试中展示自己的项目经验和实际应用能力。 总的来说,《C/C++程序员面试宝典》适合那些准备进行C/C++相关职位面试的程序员。通过系统地学习和准备,可以提高面试的成功率,更好地展示自己的技术能力和经验。不仅如此,本书还能作为C/C++技术的参考手册,帮助读者巩固和扩展自己的技术知识。 ### 回答2: 《C/C++程序员面试宝典》是一本专门为C/C++程序员准备的面试指南,它以全面的面试题目和详细的解析为主要特点。本书涵盖了C/C++程序员面试的各个方面,包括算法、数据结构、操作系统、网络编程、面向对象设计等内容。 本书通过多种形式的面试题目,对C/C++程序员的技术能力和经验进行全面考察。每个面试题目都提供了详细的解答和分析,帮助读者深入理解问题的解决思路,提高解决问题的能力。此外,本书还包括常见的面试问题和解答,以及面试技巧和注意事项,帮助读者在面试中更加自信和准备充分。 《C/C++程序员面试宝典》还特别强调了面试中的编程能力和实践经验。它提供了大量的编程题目和代码示例,通过实际的编程练习,帮助读者提高编程水平。此外,本书还介绍了C/C++编程规范和最佳实践,帮助读者写出高质量的代码。 总之,《C/C++程序员面试宝典》是一本非常全面、实用的面试指南。无论你是准备面试,还是提高编程技能,本书都会给你提供很大的帮助。通过学习本书,你可以系统地掌握C/C++程序员面试的各个方面,提高自己的技术能力,从而在面试中取得更好的成绩。 ### 回答3: "C/C++程序员面试宝典" 是一本针对C/C++程序员面试所编写的指导手册。这本书的目的是帮助程序员准备面试时可能遇到的各种问题和考点,包括面试常见问题、算法和数据结构、编程知识和技巧以及系统设计等内容。 这本宝典可以帮助准备面试的程序员了解面试官可能关注的重点和考察的方向。通过学习这本书,程序员可以更好地了解C/C++编程语言以及相关的编程概念和工具。书中还包含了许多典型的面试问题和答案示例,这可以帮助程序员在面试中更加自信地回答问题。 除了指导面试准备外,这本宝典还介绍了一些常见的编程算法和数据结构,以及如何应用它们解决问题。这对于程序员提高编程能力和解决实际问题非常有帮助。此外,宝典还提供了一些编程技巧和注意事项,帮助程序员编写更加高效、可维护和可读的代码。 总的来说,"C/C++程序员面试宝典" 是一本非常实用的指导手册,能够帮助准备C/C++程序员面试的人士更好地准备、展示自己的技能和知识。它提供了丰富的面试问题和答案示例,介绍了常见的算法和数据结构,并提供了编程技巧和注意事项。这本书对于求职者来说是一本不可或缺的工具书。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曜摆摆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值