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

2024-06-06 01:52

本文主要是介绍用幻灯片讲解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

这篇关于用幻灯片讲解C++手动内存管理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1034770

相关文章

C++右移运算符的一个小坑及解决

《C++右移运算符的一个小坑及解决》文章指出右移运算符处理负数时左侧补1导致死循环,与除法行为不同,强调需注意补码机制以正确统计二进制1的个数... 目录我遇到了这么一个www.chinasem.cn函数由此可以看到也很好理解总结我遇到了这么一个函数template<typename T>unsigned

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

SpringBoot集成XXL-JOB实现任务管理全流程

《SpringBoot集成XXL-JOB实现任务管理全流程》XXL-JOB是一款轻量级分布式任务调度平台,功能丰富、界面简洁、易于扩展,本文介绍如何通过SpringBoot项目,使用RestTempl... 目录一、前言二、项目结构简述三、Maven 依赖四、Controller 代码详解五、Service

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Python内存优化的实战技巧分享

《Python内存优化的实战技巧分享》Python作为一门解释型语言,虽然在开发效率上有着显著优势,但在执行效率方面往往被诟病,然而,通过合理的内存优化策略,我们可以让Python程序的运行速度提升3... 目录前言python内存管理机制引用计数机制垃圾回收机制内存泄漏的常见原因1. 循环引用2. 全局变

Linux系统管理与进程任务管理方式

《Linux系统管理与进程任务管理方式》本文系统讲解Linux管理核心技能,涵盖引导流程、服务控制(Systemd与GRUB2)、进程管理(前台/后台运行、工具使用)、计划任务(at/cron)及常用... 目录引言一、linux系统引导过程与服务控制1.1 系统引导的五个关键阶段1.2 GRUB2的进化优

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

C++ STL-string类底层实现过程

《C++STL-string类底层实现过程》本文实现了一个简易的string类,涵盖动态数组存储、深拷贝机制、迭代器支持、容量调整、字符串修改、运算符重载等功能,模拟标准string核心特性,重点强... 目录实现框架一、默认成员函数1.默认构造函数2.构造函数3.拷贝构造函数(重点)4.赋值运算符重载函数