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

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 内存申请

通过newdelete操作符进行动态内存管理

🚩动态申请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开辟的空间,而且会调用析构函数

🔥值得注意的是:

在这里插入图片描述

申请和释放单个元素的空间,使用newdelete操作符;申请和释放连续的空间,使用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的调用顺序

  1. 调用operator new开辟空间
  2. 调用构造函数
  3. 调用析构函数
  4. 调用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的共同点是:

都是从堆上申请空间,并且需要用户手动释放

不同的地方是:

  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在释放空间前会调用析构函数完成空间中资源的清理

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工具说明
其他工具: 内存泄漏工具比较

内存泄漏非常常见,解决方案分为两种

  1. 事前预防型,如智能指针等
  2. 事后查错型,如泄漏检测工具

希望读者们多多三连支持

小编会继续更新

你们的鼓励就是我前进的动力!

请添加图片描述

相关文章:

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 内存泄漏 希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力&#xff01; 继C语…...

Prompt提示词完整案例:让chatGPT成为“书单推荐”的高手

大家好&#xff0c;我是老六哥&#xff0c;我正在共享使用AI提高工作效率的技巧。欢迎关注我&#xff0c;共同提高使用AI的技能&#xff0c;让AI成功你的个人助理。 许多人可能会跟老六哥一样&#xff0c;有过这样的体验&#xff1a;当我们遇到一个能力出众或对事物有独到见解的…...

基于django的智能停车场车辆管理深度学习车牌识别系统

完整源码项目包获取→点击文章末尾名片&#xff01;...

【Proteus仿真】【51单片机】简易计算器系统设计

目录 一、主要功能 二、使用步骤 三、硬件资源 四、软件设计 五、实验现象 联系作者 一、主要功能 1、LCD1602液晶显示 2、矩阵按键​ 3、可以进行简单的加减乘除运算 4、最大 9999*9999 二、使用步骤 系统运行后&#xff0c;LCD1602显示数据&#xff0c;通过矩阵按键…...

洛谷P3884 [JLOI2009] 二叉树问题(详解)c++

题目链接&#xff1a;P3884 [JLOI2009] 二叉树问题 - 洛谷 | 计算机科学教育新生态 1.题目解析 1&#xff1a;从8走向6的最短路径&#xff0c;向根节点就是向上走&#xff0c;从8到1会经过三条边&#xff0c;向叶节点就是向下走&#xff0c;从1走到6需要经过两条边&#xff0c…...

《Foundation 起步》

《Foundation 起步》 引言 Foundation 是一个广泛使用的开源前端框架,由 ZURB 团队创建。它旨在帮助开发者构建响应式、可访问性和移动优先的网页。本文将为您提供一个全面的指南,帮助您从零开始学习并使用 Foundation。 Foundation 简介 什么是 Foundation? Foundatio…...

【hot100】刷题记录(6)-轮转数组

题目描述&#xff1a; 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 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生成马赛克/高斯模糊&#xff08;毛玻璃&#xff09;对比&#xff0c;Kotlin import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Canvas import android.graphics.RectF …...

ThinkPad E480安装Ubuntu 18.04无线网卡驱动

个人博客地址&#xff1a;ThinkPad E480安装Ubuntu 18.04无线网卡驱动 | 一张假钞的真实世界 遗憾的是虽然下面的方法可以解决&#xff0c;但是内核升级后需要重新安装。 基本信息 Ubuntu 18.04ThinkPad E480使用下面的命令查看 Linux 内核&#xff1a; $ uname -r 5.0.0-3…...

自然语言处理——从原理、经典模型到应用

1. 概述 自然语言处理&#xff08;Natural Language Processing&#xff0c;NLP&#xff09;是一门借助计算机技术研究人类语言的科学&#xff0c;是人工智能领域的一个分支&#xff0c;旨在让计算机理解、生成和处理人类语言。其核心任务是将非结构化的自然语言转换为机器可以…...

Ollama 运行从 ModelScope 下载的 GGUF 格式的模型

本文系统环境 Windows 10 Ollama 0.5.7 Ollama 是什么&#xff1f; Ollama 可以让你快速集成和部署本地 AI 模型。它支持各种不同的 AI 模型&#xff0c;并允许用户通过简单的 API 进行调用 Ollama 的安装 Ollama 官网 有其下载及安装方法&#xff0c;非常简便 但如果希…...

Haproxy介绍及学习

一、负载均衡(load balance)&#xff1a; 1.一种服务基于硬件设备实现的高可用反向代理技术&#xff0c;将特定的业务分担给指定的一个或者多个后端特定的服务器&#xff0c;提高了业务的并发处理能力保证业务的高可用并方便对业务后期的水平动态扩展性。 2.使用负载均衡的原因…...

【2024年华为OD机试】 (C卷,200分)- 贪心歌手(JavaScriptJava PythonC/C++)

一、问题描述 问题描述 一个歌手需要从A城前往B城参加演出&#xff0c;必须在T天内到达。途中会经过N座城市&#xff0c;且不能往回走。每两座城市之间的行程天数已知。歌手在每座城市都可以卖唱赚钱&#xff0c;但收入会随着停留天数的增加而递减。具体来说&#xff0c;第一…...

深度学习在金融风控中的应用:突破传统模型的瓶颈

深度学习在金融风控中的应用:突破传统模型的瓶颈 金融风险控制(简称“风控”)是现代金融体系中至关重要的一环,关系到金融机构的稳定性、客户的安全以及整体经济的健康运行。近年来,随着深度学习的迅猛发展,传统的风控模型正面临被颠覆的挑战,新的技术手段和思维方式正…...

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. 也进行了模型切断&#xff0c;用拉普拉斯算子找到最清晰的一帧作为训练的起始 训练了不同的模型去选择数据&#xff0c;比如用Dover去选择美观度比较好的数据&#xff0c…...

开发、科研工具汇总

一些基础教程网站 W3&#xff1a;w3school 在线教程 菜鸟&#xff1a;菜鸟教程 - 学的不仅是技术&#xff0c;更是梦想&#xff01; 开发相关参考文档 Vue2&#xff1a;Vue.js Vue3&#xff1a;Vue.js - 渐进式 JavaScript 框架 | Vue.js MDN&#xff1a;MDN Web Docs HT…...

项目部署(springboot项目)

1、安装Nginx&#xff0c;并开启 2、前端项目打包&#xff1a;npm run build:prod--->dist 3、后端项目打包&#xff1a;install--->xxx.jar 4、开放需要的端口号&#xff1a;比如我的后端项目端口号为8282&#xff0c;则需要防火墙和服务器同时开发8282端口 5、将di…...

OpenEuler学习笔记(十四):在OpenEuler上搭建.NET运行环境

一、在OpenEuler上搭建.NET运行环境 基于包管理器安装 添加Microsoft软件源&#xff1a;运行命令sudo rpm -Uvh https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm&#xff0c;将Microsoft软件源添加到系统中&#xff0c;以便后续能够从该源安装.…...

神经网络的通俗介绍

人工神经网络&#xff0c;是一种模仿人类大脑工作原理的数学模型。人类的大脑是由无数的小“工作站”组成的&#xff0c;每个工作站叫做“神经元”。这些神经元通过“电线”互相连接&#xff0c;负责接收、处理和传递信息。 一、人类大脑神经网络 人类大脑的神经网络大概长这…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...