c++内存安全问题

2023-11-05

写一个好的C++程序,我们要懂得好多东西,比如说最基本的面向对象编程思想,C++的封装、继承、多态机制,设计模式等,还有一个很重要的内容便是性能优化,像C/C++这种接近底层的语言,追求的就是性能,与之相关的一项内容便是内存管理,内存分配要合理,禁止破坏内存,不能有内存泄漏,操作不好的话,程序可能会越运行越慢,要不就是莫名其妙的crash,于是令人头疼的bug排查就这样开始了。


1、内存分配方式


在C++中,内存分为5个区:堆、栈、自由存储区、全局/静态存储区和常量存储区。


堆:由new分配的内存块,分配成功后需要我们在适当的时候通过delete释放内存,为了避免内存泄漏,new和delete要成对使用。


栈:执行函数时,函数内的局部变量(也叫自动变量)在栈上创建存储单元,函数执行结束时这些存储单元被自动释放,正因如此,函数返回局部变量的指针或引用是错误的。


自由存储区:由malloc等函数分配的内存块,与堆类似,但内存释放是用free来完成的,malloc/free与new/delete的区别是前者属于库函数,而后者是操作符,除了分配/释放内存外,还会调用类的构造/析构函数。


全局/静态存储区:全局变量和静态变量被分配到同一块存储区,生命周期和作用域与局部变量不同。


常量存储区:顾名思义,内存中存放的是常量,不允许修改。


2、堆与栈的区别


堆、栈是经常提及的两个内存块,主要区别体现在以下几个方面。


管理方式:栈由编译器自动管理,栈上的变量离开作用域之后内存被自动回收,而堆由我们自己管理,动态创建与释放内存,管理起来较为复杂。


生长方向:从整体内存空间来看,栈位于高地址,向着内存地址减小的方向生长,堆位于低地址,向着内存地址增加的方向生长。


空间大小:栈空间较小,堆空间则很大。


碎片问题:栈的数据结构形式是后进先出,内存空间是一块连续的区域,不会有内存碎片问题,而堆则不同,频繁的new/delete会造成内存空间的不连续,从而产生堆碎片,影响程序性能。


分配方式:栈有两种分配方式,静态分配和动态分配,静态分配由编译器完成,如局部变量的内存分配和释放,动态分配通过调用alloca函数实现,但内存释放是由编译器完成的。堆内存分配则都是动态分配,需要我们自己分配内存并进行内存释放。


分配效率:栈的分配使用的是机器系统提供的数据结构,在计算机底层有专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,效率较高。而堆的分配是由C/C++函数库提供的,有一定的分配算法,为了分配成功,会去搜索可用的足够大小的空间,还有可能引发用户态和内核态的切换,效率较低。


3、正确使用内存


从上面介绍的几个方面可以看出,栈高效,堆灵活,具体如何使用需要根据实际情况而定,不过使用不当的话很有可能引发系统错误,下面简单总结一下常见的情况。


错误1:内存分配未成功,却使用了这个分配结果。 
正确1: 内存分配是有可能失败的,在使用之前一定要检查分配结果是否不为NULL。


错误2:内存分配成功了,但是没有进行初始化就使用它。 
正确2:内存分配成功后,虽然一些简单数据类型的变量为0,但复杂结构的变量就不确定了,所以一定要进行初始化。


错误3:内存越界。 
正确3:内存越界常发生在数组、容器的使用中,使用前一定要确认其索引/下标有效。


错误4:没有释放已分配内存,造成内存泄漏。 
正确4:分配了内存之后忘记释放内存是可能发生的,造成内存泄漏,如果内存泄漏严重,就会造成内存不足或内存耗尽,所以malloc/free、new/delete一定要配对使用。


错误5:函数返回了指向局部变量的指针或引用。 
正确5:局部变量使用的是栈内存,函数返回时局部变量的内存被自动释放,这时再通过指针或引用来使用这个变量的话就出错了,所以返回指向局部变量的指针或引用是禁止的,如果返回值为指针或引用的话,可以返回静态变量或全局变量,或者返回堆上的变量。


错误6:误用野指针。 
正确6:用free或delete释放了内存后,还继续使用这块内存,这是有问题的,在内存释放后一定要把指针设置为NULL,避免野指针。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++内存安全问题 的相关文章

随机推荐

  • Java开发环境搭建03:idea中使用Maven

    一 Maven介绍 Maven项目对象模型 POM 可以通过一小段描述信息来管理项目的构建 报告和文档的项目管理工具软件 Maven是Apache 的开源项目 Maven使用Java开发的 运行需要Java环境的支持 Maven的作用有三点
  • leveldb之Compaction操作下之具体实现

    leveldb之Compaction操作下之具体实现 2015 05 17 19 40 438人阅读 评论 0 收藏 举报 分类 leveldb 13 版权声明 本文为博主原创文章 未经博主允许不得转载 目录 由上文可知 合并主要分为三种
  • Vue 3结合element plus(问题总结)之 table组件实现多选和清除选中

    问题描述和原因 一直出现toggleRowSelection和clearSelection不是方法 问题解决 后来发现getCurrentInstance支持访问内部组件实例 getCurrentInstance 只能在 setup 或生命
  • 人工神经网络matlab代码,matlab神经网络30例代码

    如何在matlab中建立多层bp神经网络 当你用newff的时候 里面有一个参数可以控制层数 比如说 P 0 1 2 3 4 5 6 7 8 9 10 T 0 1 2 3 4 3 2 1 2 3 4 net newff P T 5 这样表示
  • 通讯协议027——全网独有的OPC AE知识四之接口(十一)

    本文继续介绍OPC AE规范的IOPCEventSubscriptionMgt2接口的相关知识 更多通信资源请登录网信智汇 OPC AE规范描述了OPC事件服务器应该实现的对象和接口 实现在多个OPC客户端间共享事件和警报条件 可选的IOP
  • IT项目管理个人作业8

    练习题1 质量标准 要求 学历 全日制统招研究生及以上学历 专业 计算机科学 软件工程 工程管理或相关专业者优先 经验 三年 三年以上相关工作经验 年龄 30 45 论文发表 在顶级期刊上发表过三篇以上论文 技术需求 熟悉项目管理相关知识
  • 13、Efficient Geometry-aware 3D Generative Adversarial Networks

    简介 仅使用单视图 2D 照片集合无监督生成高质量的多视图一致图像和 3D 形状一直是一项长期存在的挑战 现有的3D GAN要么是计算密集型的 要么是进行不3D一致的近似 前者限制了生成图像的质量和分辨率 后者会对多视图一致性和形状质量产生
  • input框限制只能输入两位小数

    1 给数字输入框输入定义触发事件
  • 解决Mysql使用本地IP无法连接

    Mysql使用本地IP无法连接 使用localhost或127 0 0 1正常连接 问题原因 Mysql默认不会开启本地IP连接的权限 需要手动开启 解决方法 1 进入cmd 2 输入mysql u root p 密码 进入mysql 3
  • JS-----------Ajax

    目录 传统网站存在的问题 ajax概述 阿贾克斯 异步和同步的区别 Ajax运行原理 ajax的实现步骤 请求报文 Ajax的其他方法和Ajax配置信息 请求传参的几种格式 get post区别 同源政策 扩展 思维导图 传统网站存在的问题
  • Python列表操作指南:索引、切片、遍历与综合应用

    文章目录 列表 简介 创建列表 索引和切片 列表的长度 列表的拼接和重复 检查元素是否存在 列表的方法 index 方法 count 方法 列表的修改和删除 修改元素 删除元素 列表的排序和反转 添加元素 列表的拷贝 列表的遍历 列表的切片
  • Java基础练习题01基本控制流程

    1 输入一个字符 判断它是不是字母 是不是数字 是不是空格字符 public static void main String args System out print 请输入一个字符 Scanner input new Scanner S
  • 西门子S7-1200与V20变频器的USS通信

    USS通信基本原理 USS 协议 Universal Serial Interface Protocol 即通用串行接口协议 是西门子专为驱动装置开发的通用通信协议 它是一种基于串行总线进行数据通信的协议 USS 通信总是由主站发起 USS
  • NFT 项目的十大评估维度

    全文共 5383 字 阅读约需 7 分钟 目录 1 项目的艺术性 2 社区 3 团队 4 路线图 5 使用场景 6 故事性 7 成本度量 8 稀有度 9 流动性 10 趋势 如何判断某一NFT项目是否可冲 这是各大 NFT 社群里都很常见的
  • 软件测试——程序控制流图,McCabe环形复杂度

    软件测试 程序控制流图 McCabe环形复杂度 根据下边的程序流程图 完成 1 画出相应的程序控制流图 根据上述的程序流程图画出程序控制流图 由于一个条件判断语句中有复合条件表达式 故需拆开表示 2 给出控制流图的邻接矩阵 1 2 3 4
  • js中的dataset的使用

    总结 1 document querySelector 的使用 2 data 自定义属性的使用 3 dataset 获取自定义属性值的使用 转载于 https blog 51cto com 11871779 2333045
  • 社区划分的标准--模块度

    在社区发现算法中 几乎不可能先确定社区的数目 于是 必须有一种度量的方法 可以在计算的过程中衡量每一个结果是不是相对最佳的结果 模块度 Modularity 用来衡量一个社区的划分是不是相对比较好的结果 一个相对好的结果在社区内部的节点相似
  • 语言基础篇11——函数、函数参数类型、装饰器、生成器

    函数 基本结构 def func name value print f Hello value return 0 func name World 函数参数 参数默认值和五种参数类型 https docs python org 3 gloss
  • Linux之间NFS挂载,及遇到的问题

    环境 Linux1 192 168 84 139 Linux2 192 168 84 138 目的 将Linux1文件下的 opt share分享给Linux2 步骤 1 两台机器上都安装rpcbind nfs yum install y
  • c++内存安全问题

    写一个好的C 程序 我们要懂得好多东西 比如说最基本的面向对象编程思想 C 的封装 继承 多态机制 设计模式等 还有一个很重要的内容便是性能优化 像C C 这种接近底层的语言 追求的就是性能 与之相关的一项内容便是内存管理 内存分配要合理