C++传送锚点的内存寻址:内存管理
文章目录
- 1.C/C++内存分布回顾
- 2.C++内存管理
- 2.1 内存申请
- 2.2 operator new与operator delete函数
- 2.3 定位new表达式
- 3.关于内存管理的常见知识点
- 3.1 malloc/free和new/delete的区别
- 3.2 内存泄漏
- 希望读者们多多三连支持
- 小编会继续更新
- 你们的鼓励就是我前进的动力!
继C语言初步学习了内存动态管理,本篇将继续学习C++部分更深入底层逻辑的内存管理
1.C/C++内存分布回顾

程序中需要存储的数据:局部数据、静态数据和全局数据、常量数据、动态申请数据
常量和可变常量的区别
经常很多人以为加了const的变量就是常量,但其实不是的,这叫
可变常量,例如const int* ptr,其实还是可以修改的,它可以指向不同的常量整数,但不能通过该指针修改所指向的值。
🔥检查类型存储位置的小tips:

看地址存放是否相近,相近则存放在同一区域,相差巨大则存放在不同区域
2.C++内存管理
我们直到在堆上动态开辟空间需要使用malloc,realloc等函数,不仅要保证前后类型一致,还要断言空指针,感觉还是太麻烦了,所以在C++使用了更简洁方便的动态开辟函数
2.1 内存申请
通过new和delete操作符进行动态内存管理
🚩动态申请1个int类型的空间
//C
int* p1 = (int*)malloc(sizeof(int));
free(p1);//C++
int* p2 = new int;
delete p2;
🚩动态申请存储10个int类型的数组
//C
int* p3 = (int*)malloc(sizeof(int) * 10);
free(p3);//C++
int* p4 = new int[10];
delete[] p4;
🚩动态申请存储1个int类型的空间并初始化为10
int* p5 = new int(10);
delete p5;
🚩动态申请数组并初始化多个元素
int* p6 = new int[10] {1,2,3};
delete[] p6;
🚩访问开辟的数组元素
int* p4 = new int[10];
cout << p4[0] << endl;
delete[] p4;
对于指针 p4,p4[i] 实际上等价于 *(p4 + i)。也就是说,p4[0] 表示访问 p4 所指向的内存位置(即数组的第一个元素)的值
那么new和delete存在的意义是什么?
在C语言中,malloc只完成了纯粹的开空间操作,虽然calloc也能对空间初始化,但是只能将所有元素初始化
在C++中,new能够初始化部分元素,比如在链表里能够调用构造函数来完成初始化操作,省去了写BuyNewnode函数的麻烦。delete相对于free会进行严格的类型检查,确保释放的是new开辟的空间,而且会调用析构函数
🔥值得注意的是:

申请和释放单个元素的空间,使用new和delete操作符;申请和释放连续的空间,使用new[]和delete[],注意要匹配起来使用
2.2 operator new与operator delete函数
我们知道malloc是开空间,new是通过开空间+构造函数实现的,那么new的开空间可以直接调用malloc吗,答案是不可以的
首先我们要知道面向对象开空间失败喜欢抛异常而不是返回nullptr
🚩malloc开无限大空间

malloc开空间没有显示任何错误难以发现
🚩new开无限大空间

new开空间会在开空间失败后抛出异常,用try...catch...捕获异常显示具体错误
/*
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,
尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常
*/
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
// try to allocate size bytes
void *p;
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
{
// report no memory
// 如果申请内存失败了,这里会抛出bad_alloc 类型异常
static const std::bad_alloc nomem;
_RAISE(nomem);
}
return (p);
}
所以根据operator new的底层代码,new的开空间错误是要抛异常的,不能直接调用,而是new先调用operator new,然后operator new再调用malloc开空间。实际上malloc是被封装在了operator new里面的

对自定义类型进行操作时,调试状态下转到反汇编可以发现有两条call指令,一条调用operator new,一条调用构造函数,也能证实我们上面的说法,operator delete也是同理
那么又延伸出另一个问题,operator new和operator delete的调用顺序是怎么样的?
假设类Stack需要开辟动态数组_arry,容量_capacity,大小_size
Stack* p1 = new Stack;
delete p1;

p1作为指针变量存放地址,在栈上存储,然后new的空间在堆上开辟,_array又指向开辟的数组。如果按我们正常想的先调用operator delete释放堆空间,那么_array指向的数组即使调用析构函数也找不到,无法释放
因此我们可以整理出operator new和operator delete的调用顺序
- 调用operator new开辟空间
- 调用构造函数
- 调用析构函数
- 调用operator delete释放空间
2.3 定位new表达式
class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}
private:int _a;
};
// 定位new/replacement new
int main()
{// p1现在指向的只不过是与A对象相同大小的一段空间,还不能算是一个对象,因为构造函数没有执行A* p1 = (A*)malloc(sizeof(A));new(p1)A; // 注意:如果A类的构造函数有参数时,此处需要传参p1->~A();free(p1);A* p2 = (A*)operator new(sizeof(A));new(p2)A(10);p2->~A();operator delete(p2);return 0;
}
定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象,这里p1,p2只是个自定义类型,无法调用构造函数,所以要用定位new
其语法形式为:
new (place_address) type或者new (place_address) type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表
在实际应用中,定位new一般用于池化技术,也就是向内存申请一块内存池使用,因为频繁的向内存申请堆太麻烦了,所以申请一块内存池用于堆开辟空间
但是内存池的分配操作仅仅是对内存指针进行移动和管理,它只负责提供一块可用的原始内存,并没有内存初始化的操作
当使用 new 操作符来
创建对象时,它会完成两个主要步骤:首先分配内存,然后自动调用对象的构造函数对这块内存进行初始化。但内存池的分配操作只是完成了第一步,即提供内存,并没有触发构造函数调用的机制,此时定位new的作用就体现出来了,显式调用构造函数实现初始化操作
3.关于内存管理的常见知识点
3.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在释放空间前会调用析构函数完成空间中资源的清理
3.2 内存泄漏
什么是内存泄漏?
内存泄漏指因为疏忽或错误造成
程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费
如何检测内存泄漏?
在vs下,可以使用windows操作系统提供的_CrtDumpMemoryLeaks() 函数进行简单检测,该函数只报出了大概泄漏了多少个字节,没有其他更准确的位置信息
int main()
{
int* p = new int[10];
// 将该函数放在main函数之后,每次程序退出的时候就会检测是否存在内存泄漏
_CrtDumpMemoryLeaks();
return 0;
}
// 程序退出后,在输出窗口中可以检测到泄漏了多少字节,但是没有具体的位置
Detected memory leaks!
Dumping objects ->
{79} normal block at 0x00EC5FB8, 40 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
因此写代码时一定要小心,尤其是动态内存操作时,一定要记着释放。但有些情况下总是防不胜防,简单的可以采用上述方式快速定位下。如果工程比较大,内存泄漏位置比较多,不太好查时一般都是借助第三方内存泄漏检测工具处理的
在linux下内存泄漏检测: linux下几款内存泄漏检测工具
在windows下使用第三方工具: VLD工具说明
其他工具: 内存泄漏工具比较
内存泄漏非常常见,解决方案分为两种:
事前预防型,如智能指针等事后查错型,如泄漏检测工具
希望读者们多多三连支持
小编会继续更新
你们的鼓励就是我前进的动力!

相关文章:
C++传送锚点的内存寻址:内存管理
文章目录 1.C/C内存分布回顾2.C内存管理2.1 内存申请2.2 operator new与operator delete函数2.3 定位new表达式 3.关于内存管理的常见知识点3.1 malloc/free和new/delete的区别3.2 内存泄漏 希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力! 继C语…...
Prompt提示词完整案例:让chatGPT成为“书单推荐”的高手
大家好,我是老六哥,我正在共享使用AI提高工作效率的技巧。欢迎关注我,共同提高使用AI的技能,让AI成功你的个人助理。 许多人可能会跟老六哥一样,有过这样的体验:当我们遇到一个能力出众或对事物有独到见解的…...
基于django的智能停车场车辆管理深度学习车牌识别系统
完整源码项目包获取→点击文章末尾名片!...
【Proteus仿真】【51单片机】简易计算器系统设计
目录 一、主要功能 二、使用步骤 三、硬件资源 四、软件设计 五、实验现象 联系作者 一、主要功能 1、LCD1602液晶显示 2、矩阵按键 3、可以进行简单的加减乘除运算 4、最大 9999*9999 二、使用步骤 系统运行后,LCD1602显示数据,通过矩阵按键…...
洛谷P3884 [JLOI2009] 二叉树问题(详解)c++
题目链接:P3884 [JLOI2009] 二叉树问题 - 洛谷 | 计算机科学教育新生态 1.题目解析 1:从8走向6的最短路径,向根节点就是向上走,从8到1会经过三条边,向叶节点就是向下走,从1走到6需要经过两条边,…...
《Foundation 起步》
《Foundation 起步》 引言 Foundation 是一个广泛使用的开源前端框架,由 ZURB 团队创建。它旨在帮助开发者构建响应式、可访问性和移动优先的网页。本文将为您提供一个全面的指南,帮助您从零开始学习并使用 Foundation。 Foundation 简介 什么是 Foundation? Foundatio…...
【hot100】刷题记录(6)-轮转数组
题目描述: 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转…...
Android createScaledBitmap与Canvas通过RectF drawBitmap生成马赛克/高斯模糊(毛玻璃)对比,Kotlin
Android createScaledBitmap与Canvas通过RectF drawBitmap生成马赛克/高斯模糊(毛玻璃)对比,Kotlin import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Canvas import android.graphics.RectF …...
ThinkPad E480安装Ubuntu 18.04无线网卡驱动
个人博客地址:ThinkPad E480安装Ubuntu 18.04无线网卡驱动 | 一张假钞的真实世界 遗憾的是虽然下面的方法可以解决,但是内核升级后需要重新安装。 基本信息 Ubuntu 18.04ThinkPad E480使用下面的命令查看 Linux 内核: $ uname -r 5.0.0-3…...
自然语言处理——从原理、经典模型到应用
1. 概述 自然语言处理(Natural Language Processing,NLP)是一门借助计算机技术研究人类语言的科学,是人工智能领域的一个分支,旨在让计算机理解、生成和处理人类语言。其核心任务是将非结构化的自然语言转换为机器可以…...
Ollama 运行从 ModelScope 下载的 GGUF 格式的模型
本文系统环境 Windows 10 Ollama 0.5.7 Ollama 是什么? Ollama 可以让你快速集成和部署本地 AI 模型。它支持各种不同的 AI 模型,并允许用户通过简单的 API 进行调用 Ollama 的安装 Ollama 官网 有其下载及安装方法,非常简便 但如果希…...
Haproxy介绍及学习
一、负载均衡(load balance): 1.一种服务基于硬件设备实现的高可用反向代理技术,将特定的业务分担给指定的一个或者多个后端特定的服务器,提高了业务的并发处理能力保证业务的高可用并方便对业务后期的水平动态扩展性。 2.使用负载均衡的原因…...
【2024年华为OD机试】 (C卷,200分)- 贪心歌手(JavaScriptJava PythonC/C++)
一、问题描述 问题描述 一个歌手需要从A城前往B城参加演出,必须在T天内到达。途中会经过N座城市,且不能往回走。每两座城市之间的行程天数已知。歌手在每座城市都可以卖唱赚钱,但收入会随着停留天数的增加而递减。具体来说,第一…...
深度学习在金融风控中的应用:突破传统模型的瓶颈
深度学习在金融风控中的应用:突破传统模型的瓶颈 金融风险控制(简称“风控”)是现代金融体系中至关重要的一环,关系到金融机构的稳定性、客户的安全以及整体经济的健康运行。近年来,随着深度学习的迅猛发展,传统的风控模型正面临被颠覆的挑战,新的技术手段和思维方式正…...
LLM - 大模型 ScallingLaws 的指导模型设计与实验环境(PLM) 教程(4)
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/145323420 免责声明:本文来源于个人知识与公开资料,仅用于学术交流,欢迎讨论,不支持转载。 Scaling Laws (缩放法则) 是大模型领域中,用于描述 模型性能(Loss) 与…...
hunyuan 混元学习
使用了5个subset,也是用了text-image和text-video进行训练的 也是进行了复杂的视频选择。同movie gen. 也进行了模型切断,用拉普拉斯算子找到最清晰的一帧作为训练的起始 训练了不同的模型去选择数据,比如用Dover去选择美观度比较好的数据,…...
开发、科研工具汇总
一些基础教程网站 W3:w3school 在线教程 菜鸟:菜鸟教程 - 学的不仅是技术,更是梦想! 开发相关参考文档 Vue2:Vue.js Vue3:Vue.js - 渐进式 JavaScript 框架 | Vue.js MDN:MDN Web Docs HT…...
项目部署(springboot项目)
1、安装Nginx,并开启 2、前端项目打包:npm run build:prod--->dist 3、后端项目打包:install--->xxx.jar 4、开放需要的端口号:比如我的后端项目端口号为8282,则需要防火墙和服务器同时开发8282端口 5、将di…...
OpenEuler学习笔记(十四):在OpenEuler上搭建.NET运行环境
一、在OpenEuler上搭建.NET运行环境 基于包管理器安装 添加Microsoft软件源:运行命令sudo rpm -Uvh https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm,将Microsoft软件源添加到系统中,以便后续能够从该源安装.…...
神经网络的通俗介绍
人工神经网络,是一种模仿人类大脑工作原理的数学模型。人类的大脑是由无数的小“工作站”组成的,每个工作站叫做“神经元”。这些神经元通过“电线”互相连接,负责接收、处理和传递信息。 一、人类大脑神经网络 人类大脑的神经网络大概长这…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
Linux部署私有文件管理系统MinIO
最近需要用到一个文件管理服务,但是又不想花钱,所以就想着自己搭建一个,刚好我们用的一个开源框架已经集成了MinIO,所以就选了这个 我这边对文件服务性能要求不是太高,单机版就可以 安装非常简单,几个命令就…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
[10-1]I2C通信协议 江协科技学习笔记(17个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17...
