当前位置: 首页 > news >正文

内存管理--3.用幻灯片讲解C++手动内存管理

用幻灯片讲解C++手动内存管理

1.栈内存的基本元素

在这里插入图片描述

2.栈内存的聚合对象

在这里插入图片描述

3.手动分配内存和释放内存

注意:手动分配内存,指的是在堆内存中。
除非实现自己的数据结构,否则永远不要手动分配内存!
即使这样,您也应该通过std::allocator_traits使用分配器。(注:allocator_traits是STL库的对自定义内存分配器的统一接口)
在这里插入图片描述

4.在堆上手动分配内存

p被当做拥有一个原始指针。这幅幻灯片有个bug,不知各位看出来没有?
在这里插入图片描述

5.手动分配数组内存和释放数组内存

注意:释放数组内存delete后一定要带[ ],否则程序将产生不可预知的后果,大概率是报内存错误后程序挂掉,因为你只释放了数组的一个元素的内存,其它内存没有释放,造成了内存泄漏。
作者再次强调了:
除非实现自己的数据结构,否则永远不要手动分配内存!
即使这样,您也应该通过std::allocator_traits使用分配器。
在这里插入图片描述

6.手动分配数组内存

在这里插入图片描述

7.不要使用拥有的原始指针

  • 指针指向已经删除的内存怎么办?
  • 如果指针指向其他进程保留的内存怎么办?
  • 我们必须手动跟踪分配(new)和解除分配(delete)
  • 非常容易出错,可能导致难以捕捉的bug

下图就是一个经典的错误,释放内存后,用户忘记了已经释放,然后又向p指向的内存写入值,产生内存错误,程序挂掉!
在这里插入图片描述

8.黑暗时代和现代C++时代

黑暗时代(C++11之前)

  • 拥有原始指针
  • 经常在不同的代码点显式的new和显示的delete
  • 非直观界面
  • 内存易泄漏

现代C++时代

智能指针
  • 自动删除对象
  • 自我文档化接口/所有权(指由智能指针来管理内存,不需要用户关系具体细节)
  • 没有内存泄漏
    在这里插入图片描述

9.地址检测器(ASAN)

  • 支持的编译器:g++、clang++
  • 检测内存错误
    • 内存泄漏
    • 访问已经释放的内存
    • 访问不正确的堆栈区域
  • 使用附加说明检测您的代码
    • 运行时间增加约70%
    • 内存使用量增加了大约3倍

注:ASAN是谷歌开发的一个动态内存检测器,可以检测出各种内存相关的错误。
在这里插入图片描述

10.示例:检测空指针

在这里插入图片描述

11.使用ASAN

在这里插入图片描述

12.Valgrind工具

(Valgrind 是一个强大的内存调试和性能分析工具集,广泛应用于 C/C++ 等编程语言的软件开发和分析中。)

检测常见运行时错误。

  • 读/写释放的内存或不正确的堆栈区域。
  • 使用未初始化的值。
  • 不正确的内存释放,如双重释放。
  • 滥用内存分配函数。
  • 内存泄漏-无意内存泄漏通常与程序逻辑缺陷有关,这些缺陷导致内存指针在重新分配之前丢失。

Windows:

Dr.Memory (www.drmemory.org) (Windows平台上的C/C++内存错误检查器)
Windows 10 64位:在WSL中的Valgrind
在这里插入图片描述

13.Valgrind使用

在这里插入图片描述
在这里插入图片描述

14.标准库中的异常

operator new 会抛出以下异常:

  • std::bad_alloc 如果内存没有被成功分配
  • std::bad_new_array_size 如果数组长度小于0或者太大
    在这里插入图片描述

15.异常安全性的含义

内存泄漏的潜在来源
如下图的示例,如果文件不存在抛出异常后则就会造成buf指向的内存没有被释放,内存泄漏!
在这里插入图片描述

16.智能指针工程及其异常安全性

  • C++标准要求:
    • 所有函数参数必须在进入函数前求值。
    • 未指定函数参数求值顺序。
  • 6种参数求值顺序的两种。
    在这里插入图片描述

下图可能会造成内存泄漏

可能的求值顺序:

  1. new Widget{}
  2. Gadget{}
  3. unique_ptr{}

如果Gadget构造函数抛出异常

  • Widget对象已经构建(在堆上)
  • unique_ptr尚未获取Widget对象的所有权
  • Widget对象泄漏
    在这里插入图片描述
    下图代码就不可能有内存泄露:
  • 调用make_unique()在Gadjet构造函数调用之前或之后完全计算。
  • 如果Gadget构造函数抛出异常:
    • 则Widget已经被unique_ptr所拥有,
    • 无论如何,Widget都会被正确地销毁。
  • 使用 make_unique和make_shared来创建智能指针!
    在这里插入图片描述
    希望文章对您有所帮助,整理不易,请随手点个赞!原文链接:hackingcpp.com

相关文章:

  • memory动态内存管理学习之unique_ptr
  • 探究Vue源码:深入理解diff算法
  • Codeforces Round 950 (Div. 3)
  • Zemax中FFT PSF和惠更斯PSF的区别?
  • GA/T 1400视频汇聚平台EasyCVR级联后,平台显示无通道是什么原因?
  • 【JavaScript脚本宇宙】创造声音的魔法:深入了解Web音频处理库
  • Spring Data Jpa 实现批量插入或更新
  • 【职业思考】程序员应该有什么职业素养?
  • 怎么排查native层的bug
  • DevOps后时代,构建基于价值流的平台化工程
  • f-stack和DPDK
  • hadoop疑难问题解决_NoClassDefFoundError: org/apache/hadoop/fs/adl/AdlFileSystem
  • 强化学习面试题
  • Sui Generis如何为艺术家弥合Web3的鸿沟
  • 详细说说机器学习在交通领域的应用
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • Centos6.8 使用rpm安装mysql5.7
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • Flex布局到底解决了什么问题
  • IDEA常用插件整理
  • JavaScript异步流程控制的前世今生
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • Js基础——数据类型之Null和Undefined
  • MySQL-事务管理(基础)
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • python docx文档转html页面
  • vue2.0项目引入element-ui
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 基于遗传算法的优化问题求解
  • 批量截取pdf文件
  • 深度学习中的信息论知识详解
  • Python 之网络式编程
  • 函数计算新功能-----支持C#函数
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • #职场发展#其他
  • (done) 两个矩阵 “相似” 是什么意思?
  • (LeetCode 49)Anagrams
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (四)库存超卖案例实战——优化redis分布式锁
  • (一)spring cloud微服务分布式云架构 - Spring Cloud简介
  • (源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .NET CF命令行调试器MDbg入门(一)
  • .net core 依赖注入的基本用发
  • .xml 下拉列表_RecyclerView嵌套recyclerview实现二级下拉列表,包含自定义IOS对话框...
  • @Repository 注解
  • @transactional 方法执行完再commit_当@Transactional遇到@CacheEvict,你的代码是不是有bug!...
  • [20150629]简单的加密连接.txt
  • [BROADCASTING]tensor的扩散机制
  • [C#]C#学习笔记-CIL和动态程序集
  • [CF703D]Mishka and Interesting sum/[BZOJ5476]位运算
  • [dfs] 图案计数
  • [Electron] 将应用打包成供Ubuntu、Debian平台下安装的deb包
  • [Excel]如何找到非固定空白格數列的條件數據? 以月份報價表單為例