C++内存管理看这一篇就够了

目录
  • 1 内存分布图
  • 2 C语言和C++内存分配实现
    • 2.1 C语言实现
    • 2.2 C++实现
      • new的原理
      • delete的原理
  • 3 C语言和C++内存管理区别
  • 4 内存泄漏
  • 总结

1 内存分布图

注意:

1.向下生长:地址由高到低
2.向上生长:地址由低到高
3.栈又叫堆栈,非静态局部变量/函数参数/返回值等等
4.堆用于程序运行时动态内存分配

2 C语言和C++内存分配实现

2.1 C语言实现

malloc函数

 void *malloc(size_t size)

分配所需的内存空间,单位是字节,并返回一个指向它的指针。

int* ptr_int = (int*)malloc(4*sizeof(int));//开辟空间
free(ptr_int);//释放空间

calloc函数

void *calloc(size_t nitems, size_t size)

分配所需的内存空间,并返回一个指向它的指针。nitems – 要被分配的元素个数。size – 元素的大小。malloc 和 calloc 之间的不同点是,malloc 不会设置内存为零,而 calloc 会设置分配的内存为零。

char* ptr_char = (char*)calloc(4, sizeof(char));
free(ptr_char);

realloc

void *realloc(void *ptr, size_t size)

尝试重新调整之前调用 malloc 或 calloc 所分配的ptr 所指向的内存块的大小。ptr – 指针指向一个要重新分配内存的内存块,该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的。如果为空指针,则会分配一个新的内存块,且函数返回一个指向它的指针。

size – 内存块的新的大小,以字节为单位。如果大小为 0,且 ptr 指向一个已存在的内存块,则 ptr 所指向的内存块会被释放,并返回一个空指针。

int* ptr_int = (int*)malloc(4*sizeof(int));
char* ptr_char = (char*)calloc(4, sizeof(char));

int* ptr_int1 = (int*)realloc(ptr_int, 8 * sizeof(int));
char* ptr_char1 = (char*)realloc(ptr_char, 8 * sizeof(char));

2.2 C++实现

new和delete的实现原理

1 内置类型

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

2 自定义类型

new的原理

1.调用operator new函数申请空间

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

delete的原理

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

2.调用operator delete函数释放对象的空间

3 C语言和C++内存管理区别

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

1.malloc和free是函数,new和delete是操作符

2.malloc申请的空间不会初始化,new可以初始化

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

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

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

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

4 内存泄漏

什么是内存泄漏:

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

内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。

堆内存泄漏(Heap leak)

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

系统资源泄漏

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

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • 深入理解C++中的new/delete和malloc/free动态内存管理及区别介绍

    malloc/free和new/delete的区别 malloc/free是C/C++标准库的函数:new/delete是C++操作符. malloc/free只是动态分配内存空间/释放空间:new/delete除了分配空间还会调用构造函数和析构函数进行初始化与清理资源. malloc/free需要手动计算类型大小且返回值类型为void*:new/delete可自动计算类型的大小,返回对应类型的指针. malloc/free管理内存失败会返回0:new/delete等的方式管理内存失败会抛出异常

  • 关于C/C++内存管理示例详解

    1.内存分配方式 在C++中,内存分成五个区,分别是堆.栈.自由存储区.静态存储区和常量存储区. 1) 栈 执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放.栈内存分配运算内置处理器指令集中,效率很高,但分配的内存容量有限. 2) 堆 由new分配的内存块,释放由程序员控制.如果程序员没有释放,那么就在程序结束的时候,被操作系统回收. 3) 自由存储区 由malloc等分配的内存块,用free结束自己的生命. 4) 静态存储区 全局变量和静态变量被分配到

  • C/C++中的内存管理小结

    前言 我们最初熟知的内存开辟方式: int val = 20: 在栈空间上开辟4个字节 char array[10]: 在栈空间上开辟10个字节的连续空间 上述开辟空间的方式有两个特点: 空间开辟大小是固定的. 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配. 但是对于空间的需求,不仅仅是上述的情况,有时候我们需要的空大小在程序运行时才能知道,那此时静态的开辟空间的方式就不能满足了,我们这时候只能试试动态内存开辟. 这篇博客就来带大家梳理一下C/C++中的内存管理. 一:C/C

  • 详解C/C++内存管理

    C/C++赋予程序员管理内存的自由,是C/C++语言特色,虽然这引入了复杂度和危险性,但另一方面,它也增加了控制力和灵活性,是C/C++独特之处,亦是强大之处. C/C++内存分布 让我们先来看看下面这段代码: int globalVar = 1; static int staticGlobalVar = 1; void Test() { static int staticVar = 1; int localVar = 1; int num1[10] = { 1, 2, 3, 4 }; char

  • 一文秒懂C语言/C++内存管理(推荐)

    C 语言内存管理指对系统内存的分配.创建.使用这一系列操作.在内存管理中,由于是操作系统内存,使用不当会造成毕竟麻烦的结果.本文将从系统内存的分配.创建出发,并且使用例子来举例说明内存管理不当会出现的情况及解决办法. 一.内存 在计算机中,每个应用程序之间的内存是相互独立的,通常情况下应用程序 A 并不能访问应用程序 B,当然一些特殊技巧可以访问,但此文并不详细进行说明.例如在计算机中,一个视频播放程序与一个浏览器程序,它们的内存并不能访问,每个程序所拥有的内存是分区进行管理的. 在计算机系统中

  • C++内存管理看这一篇就够了

    目录 1 内存分布图 2 C语言和C++内存分配实现 2.1 C语言实现 2.2 C++实现 new的原理 delete的原理 3 C语言和C++内存管理区别 4 内存泄漏 总结 1 内存分布图 注意: 1.向下生长:地址由高到低 2.向上生长:地址由低到高 3.栈又叫堆栈,非静态局部变量/函数参数/返回值等等 4.堆用于程序运行时动态内存分配 2 C语言和C++内存分配实现 2.1 C语言实现 malloc函数 void *malloc(size_t size) 分配所需的内存空间,单位是字节

  • SpringBoot后端接口的实现(看这一篇就够了)

    摘要:本文演示如何构建起一个优秀的后端接口体系,体系构建好了自然就有了规范,同时再构建新的后端接口也会十分轻松. 一个后端接口大致分为四个部分组成:接口地址(url).接口请求方式(get.post等).请求数据(request).响应数据(response).如何构建这几个部分每个公司要求都不同,没有什么"一定是最好的"标准,但一个优秀的后端接口和一个糟糕的后端接口对比起来差异还是蛮大的,其中最重要的关键点就是看是否规范! 本文就一步一步演示如何构建起一个优秀的后端接口体系,体系构建

  • 程序员最实用的 SQL 语句收藏,看完这篇就够了

    前言 文章沿着设计一个假想的应用 awesome_app 为主线,从零创建修改数据库,表格,字段属性,索引,字符集,默认值,自增,增删改查,多表查询,内置函数等实用 SQL 语句.收藏此文,告别零散又低效地搜索经常使用的 SQL 语句.所有 SQL 都在 MySQL 下通过验证,可留着日后回顾参考,也可跟着动手一起做,如果未安装 MySQL 可参考 <macOS 安装 mysql> (windows 安装大同小异). 1. 创建 1.1 创建数据库 语法:create database db_

  • Java-lambda表达式入门看这一篇就够了

    概述 Lambda表达式,也可称为闭包,是JDK8的新特性.Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中),可以使代码变的更加简洁紧凑.Lambda表达式是一个可传递的代码块,可以在以后执行一次或多次. 名字起源是以前还没有计算机时,逻辑学家Alonzo Church想要形式化的表示能有效计算的数学函数,使用了希腊字母lambda( λ \lambda λ)来标记参数,从那以后,带参数变量的表达式就被称为lambda表达式. lambda表达式本质是一个匿名函数,比如以下

  • C语言学好递归看这一篇就够了

    前言 在一定的时间.空间限制下,人的体力有限,思维力也有限,递归思维对实践最有用的指导,就是把脑力集中于定义问题这个关键点上,不用去找解题的过程.定义(问题)即解决(问题),定义即解决! 让大问题变成规模更小的问题并立即获得解决,以此作为基础,让我们轻松解决函数本身定义的问题.所以,递归在编程中同样是很重要的一个知识点. 提示:以下是本篇文章正文内容 一.递归是什么? 先来看一下定义: 程序调用自身的编程技巧称为递归( recursion). 简单来说,就是在一个函数里面调用函数自己本身. 举个

  • 关于Android多渠道打包问题看这一篇就够了

    目录 一.多渠道配置 二.注意事项 Android 多渠道打包看这一篇就够了 本文三个流程 一.多渠道配置 1.多渠道配置 2.不同渠道不同签名配置 3.不同渠道不同资源文件配置 4.不同渠道不同依赖配置 二.注意事项 三.打包 1.命令行打包 2.IDE 打包 多渠道配置(2 种方式) 1.可写在主模块(app)的 build.gradle 下 android { compileSdkVersion 29 buildToolsVersion "29.0.3" defaultConfi

  • SpringBoot中并发定时任务的实现、动态定时任务的实现(看这一篇就够了)推荐

    一.在JAVA开发领域,目前可以通过以下几种方式进行定时任务 1.单机部署模式 Timer:jdk中自带的一个定时调度类,可以简单的实现按某一频度进行任务执行.提供的功能比较单一,无法实现复杂的调度任务. ScheduledExecutorService:也是jdk自带的一个基于线程池设计的定时任务类.其每个调度任务都会分配到线程池中的一个线程执行,所以其任务是并发执行的,互不影响. Spring Task:Spring提供的一个任务调度工具,支持注解和配置文件形式,支持Cron表达式,使用简单

  • Mybatis配置解析看这一篇就够了

    目录 核心配置文件 environments元素 mappers元素 Mapper文件 Properties优化 typeAliases优化 生命周期和作用域 总结 核心配置文件 mybatis-config.xml 系统核心配置文件 MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息. 能配置的内容如下: configuration(配置) properties(属性) settings(设置) typeAliases(类型别名) typeHandlers(类型处

  • Python eval() 函数看这一篇就够了

    目录 一.语法和参数 二.expression参数示例 三.globals参数示例 四.locals参数示例 五.eval函数的危险之处 六.eval()函数官方文档 附eval()函数常见作用有 总结 一.语法和参数 在Python中evel()函数的语法格式为eval(expression, globals=None, locals=None),注意后面还有globals参数和locals参数.eval()函数用于执行一个字符串表达式,并且返回该表达式的值.与eval相近的有exec函数,该

  • python操作Excel神器openpyxl看这一篇就够了

    目录 Excel xlsx Openpyxl 创建新文件 Openpyxl 写入单元格 Openpyxl 附加值 OpenPyXL 读取单元格 OpenPyXL 读取多个单元格 Openpyxl 按行迭代 Openpyxl 按列迭代 统计 Openpyxl 过滤器&排序数据 Openpyxl 维度 工作表 合并单元格 Openpyxl 冻结窗格 Openpyxl 公式 OpenPyXL 图像 Openpyxl 图表 总结 Excel xlsx 在本教程中,我们使用 xlsx 文件. xlsx 是

随机推荐