C++:内存管理:C++内存管理详解

news2024/11/23 1:33:01

C++语言内存管理是指:对系统的分配、创建、使用这一系列操作。在内存管理中,由于是操作系统内存,使用不当会造成很麻烦的后果。本文将从系统内存的分配、创建出发,并且结合例子来说明内存管理不当会造成的结果以及解决方案。

一:内存

在计算机中,每个应用程序之间的内存是相互独立的,通常情况下应用程序A并不能访问应用程序B,当然我们可以使用一种特殊技术,让他们可以互相访问,但这个不是本文的重点。比如在计算机中,一个视频播放程序与一个浏览器程序,他们的内存并不能访问,每个程序所拥有的内存是分区进行管理的。

在计算机系统中,运行程序A将会在内存中开启程序A的内存区域1,运行程序B将会在内存中开辟程序B的内存区域2,内存1和内存2之间逻辑分离。

 1.1 内存四个区

在程序A开辟的内存区域1会被分为几个区域,这就是内存四区,内存四区分为栈区、堆区、数据区和代码区。

栈区:指的是存储一些临时变量的区域,临时变量包括了局部变量、返回值、参数、返回地址等,当这些变量超出了当前作用域时将会自动弹出。该栈的最大存储是有大小的且固定的,超过该代销将会造成栈溢出。

堆区:是一个比较大的内存空间,主要用于对动态内存的分配,在程序开发中一般是开发人员进行分配和释放,若在程序结束时都还未释放,系统将自动进行回收。

数据区:主要存放全局变量、常量、静态变量,数据区又可以划分为:全局区和静态区,全局变量和静态变量将会存放到该区域。

代码区:比较简单,主要存储可执行代码,该区域的属性是只读的。

1.2 通过代码证实内存四区的底层结构

栈区

由于栈区和堆区的底层结构比较直观的表现,我们在此使用代码只演示这两个概念来查看代码观察栈区的内存地址分配情况。

// main.cpp
#include<iostream>
int main() {
	int a = 0;
	int b = 0;
	int c = 0;
	printf("变量a的地址: %d", &a);
	printf("\n变量b的地址: %d", &b);
	printf("\n变量c的地址: %d", &c);

	// 打印结果

}

 

 为什么它们之间的地址不是增加而是减少呢?那是因为栈区的一种数据存储结构为先进后出,如图:

                                                 

  1. 首先栈的顶部为地址的“最小”索引,随后往下依次增大,但是由于堆栈的特殊结果,我们将变量a先进行存储,那么它的一个索引地址将会是最大的,随后依次减少。(即 6422300)
  2. 第二次存储的变量时b,该值得地址索引比a小4个字节(因为int类型在32位系统中占4个字节),所以在a地址的基础上减少4个字节(即:6422296)
  3. 第三次存储变量c,该值得地址索引比b小4个字节(即:6422292)
  4. 第三次存储变量d,该值得地址索引比c小1个字节(即:6422291),因为char字符占一个字节
  5. 由于a、b、c、d这四个变量同属一一个栈内,所以他们地址的索引是连续性的,但是如果我们创建一个静态变量将会是怎样的了 ?

数据区

我们定义一个全局变量和 静态变量看看效果


#include<iostream>
int e = 0;
int main() {
	static int f = 0;
	printf("\n var e address: %d", &e);
	printf("\nvar f address: %d", &f);

}

// 打印结果
 var e address: 8430692
 var f address: 8430696

从这个例子可以看出,数据区的地址不是栈结构,它是由低向高分配的,这里还是和栈区有点区别的。

以上例子其实也说明了栈区的特性,就是容量具有固定大小,超过最大容量将会造成栈溢出


#include<iostream>

int main() {
	char char_arr[1024 * 1000000000];
	char_arr[0] = 'a';
}

// 编译之后直接会报错

 1.3 :为了解决上面这个问题(开辟大容量内存)

堆并没有栈一样的结构,也没有栈一样的先进后出。我们需要人为的对内存进行分配使用。


#include<iostream>
#include<string>

int main() {

	//定义一个指针:指向一个大容量的内存地址
	char* p1 = (char*)malloc(1024 * 1000);

	// 把字符串"here is heap"赋值到指针 p1指向的空间中
	std::string s = "here is heap";
	strcpy_s(p1, 1024,s.c_str());

	//打印内存空间的地址
	printf("p1 storage address: %d", p1);
	printf("\np1 storage: %s", p1);
}


//打印结果

p1 storage address: 19443776
p1 storage: here is heap

多说一点

char *p=new char[10];
p="hello";
delete p[];//此步释放时将报错❌

这是因为:在C++中,字符串常量"hello"被保存在常量存储区,而p="hello"操作是改变了指针的指向,使得指针p指向了常量存储区的"hello",造成了初始在堆上开辟的内存泄露,而delete无法释放常量存储区的内存,导致出错。

二:malloc和free使用

在 C 语言(不是 C++)中,malloc 和 free 是系统提供的函数,成对使用,用于从堆中分配和释放内存。malloc 的全称是 memory allocation 译为“动态内存分配”。

2.1 malloc和free

在开辟堆空间时我们使用的函数为 malloc,malloc 在 C 语言中是用于申请内存空间,malloc 函数的原型如下:

void *malloc(size_t size);

 在 malloc 函数中,size 是表示需要申请的内存空间大小,申请成功将会返回该内存空间的地址;申请失败则会返回 NULL,并且申请成功也不会自动进行初始化。

细心的同学可能会发现,该函数的返回值说明为 void *,在这里 void * 并不指代某一种特定的类型,而是说明该类型不确定,通过接收的指针变量从而进行类型的转换。在分配内存时需要注意,即时在程序关闭时系统会自动回收该手动申请的内存 ,但也要进行手动的释放,保证内存能够在不需要时返回至堆空间,使内存能够合理的分配使用。

未完待续:看完这篇你还能不懂C语言/C++内存管理?

 把内存管理理解好,C语言真的不难学。今天带你“攻破”内存管理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/25945.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Spring】Spring AOP的实现原理

目录 什么是AOP AOP的作用 AOP的优点 AOP框架 Spring AOP AspectJ 术语 1.Target ——目标类 2.Joinpoint ——连接点 3.Pointcut——切入点 4.Advice——通知/增强 5.Weaving——植入 6.Proxy——代理类 7.Aspect——切面 底层逻辑 开发流程 1.导入依…

八、手把手教你搭建SpringCloudAlibaba之Sentinel服务降级之慢调用

SpringCloud Alibaba全集文章目录&#xff1a; 零、手把手教你搭建SpringCloudAlibaba项目 一、手把手教你搭建SpringCloud Alibaba之生产者与消费者 二、手把手教你搭建SpringCloudAlibaba之Nacos服务注册中心 三、手把手教你搭建SpringCloudAlibaba之Nacos服务配置中心 …

贪心算法应用

1. 算法思想 贪心算法一般分为如下四步&#xff1a; 将问题分解为若干个子问题找出适合的贪心策略求解每一个子问题的最优解将局部最优解堆叠成全局最优解 即选择每一阶段的局部最优&#xff0c;从而达到全局最优。 2. 最大自序和 题目描述 题目链接 给你一个整数数组 n…

用Servlet 编写hello world

第一次接触 Servlet&#xff0c;使用 Servlet 编写代码并配合 Tomcat 在浏览器中展示代码效果&#xff0c;也算是自己这么长时间学习java的一次飞升吧。 本文总结了六步使用 Servlet 编写 helloworld步骤&#xff0c;希望给初学Servlet的同学一些帮助。 0、准备工作 1&#xff…

Python 随机函数random详解

介绍这7个随机数的方法应用&#xff1a; 1、random.random&#xff08;&#xff09;查看源码 说明&#xff1a;用于生成一个0到1的随机符点数: 0 < x < 1.0 import random for i in range(10):print(random.random()) 2、random.uniform&#xff08;&#xff09;查看源码…

深度学习(14)—— 关于Tensorboard

深度学习&#xff08;14&#xff09;—— 关于Tensorboard 文章目录深度学习&#xff08;14&#xff09;—— 关于Tensorboard前言1. “一参数一图”2.“多参数一图”3. “一栏一图”4. “一栏多图”在模型训练过程中loss和acc都会发生变化&#xff0c;常常需要记录这些值&…

Spring Security(2)

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e; 前面已经把需要的环境准备好了&#xff0c;包括数据库和SQL语句&#xff0c;现在再来写代码。至于安装MySQL什么的就跳过去了&#xff0c;娘度子里面一大把。 先…

保护Excel表格的4种常用方法

今天来说说&#xff0c;根据不同需求&#xff0c;我们可以给Excel表格设置保护的4种常用方法&#xff0c;记得保存收藏&#xff0c;总有一个适合你。 方法一&#xff1a; 如果不想Excel表格被他人随意打开&#xff0c;可以设置“打开密码”&#xff0c;这样只有输入设置的密码…

OpenSergo 流量路由:从场景到标准化的探索

流量路由&#xff0c;顾名思义就是将具有某些属性特征的流量&#xff0c;路由到指定的目标。流量路由是流量治理中重要的一环&#xff0c;多个路由如同流水线一样&#xff0c;形成一条路由链&#xff0c;从所有的地址表中筛选出最终目的地址集合&#xff0c;再通过负载均衡策略…

git ssh permission denied解决办法

git ssh permission denied解决办法 1. SSH配置 参考链接 SSH配置文档 2. ssh报错(permission denied) 解决方式&#xff1a; 找到git安装目录 进入etc/ssh文件夹内&#xff0c;找到ssh_config文件&#xff0c;在# Added by git-extra后面添加t替换代码具体参考下面图片 H…

2022强网拟态pwn-store

2022强网拟态pwn-store 这是一个综合题&#xff0c;io链接的构造&#xff0c;orw的系统位数的限制 首先是这个沙箱&#xff0c;64位只有r和w&#xff0c;一开始看的时候很纳闷多了32位的限制&#xff0c;64位还没有o&#xff0c;查了一下才知道这样的seccomp-tools是以64位的…

Design Compiler工具学习笔记(4)

目录 引言 知识储备 实际操作 设计源码 Vivado2018.3仿真 VCS2016仿真 Tcl脚本 约束脚本 MY_TOP.tcl 运行脚本 RUN.tcl 引言 本篇继续学习 DC的基本使用。本篇主要学习 DC 需要的环境约束。 前文链接&#xff1a; Design Compiler工具学习笔记&#xff08;1&#x…

【苹果推iMessage位置推相册共享推送】软件安装上传到appstore都是需要的Activity

推荐内容IMESSGAE相关 作者推荐内容iMessage苹果推软件 *** 点击即可查看作者要求内容信息作者推荐内容1.家庭推内容 *** 点击即可查看作者要求内容信息作者推荐内容2.相册推 *** 点击即可查看作者要求内容信息作者推荐内容3.日历推 *** 点击即可查看作者要求内容信息作者推荐…

maxcompute优化慢执行语句思路

maxcompute慢执行任务优化如何锁定慢执行任务&#xff1f;判断是何种类型的慢任务如何锁定慢执行任务&#xff1f; 第一步&#xff1a;如果是周期任务可以通过任务执行日志中的LogView 链接查看 &#xff0c;如果是临时任务则通过maxcompute命令行 执行wait instanceId instanc…

现代密码学导论-2-古典密码及其密码分析

目录 1.3 古典密码和密码分析 1.3.1 凯撒密码 Caesar’s cipher 1.3.2 移位密码 shift cipher 1.3.3 充分密钥空间原则 1.3.4 单表代换密码 mono-alphabetic substitution cipher 1.3.5 利用字母频率对移位密码的一种改进攻击 1.3.6 维吉尼亚密码(多表代换密码)Vigenere…

Ansys Zemax | 使用 OpticStudio 进行闪光激光雷达系统建模(上)

前言 在消费类电子产品领域&#xff0c;工程师可利用激光雷达实现众多功能&#xff0c;如面部识别和3D映射等。尽管激光雷达系统的应用非常广泛而且截然不同&#xff0c;但是 “闪光激光雷达” 解决方案通常都适用于在使用固态光学元件的目标场景中生成可检测的点阵列。凭借具…

教育行业数据可视化应用方案与实践

教育行业背景介绍 随着信息技术发展&#xff0c;教育领域中的学习方式、教学模式、教学内容均已发生重大变革&#xff0c;以云计算、人工智能、物联网、大数据等技术的结合&#xff0c;“智慧教育”的需求也变的紧迫&#xff0c;需要围绕“智慧教育”而产生的产品和解决方案也…

课程思政案例----简道云零代码应用开发实训平台

为了更好推动零代码开发课程的思政建设&#xff0c;在传递大数据相关知识和技能的同时帮助学生塑造正确的世界观、人生观和价值观。我们整理了与简道云平台结合的应用案例&#xff0c;开放给全国各大高校使用。 1、杨卫红&#xff1a;一位55岁不懂代码的农经员&#xff0c;为家…

Windows下将文件夹映射为磁盘

Windows下将文件夹映射为磁盘背景描述方法一&#xff1a;使用命令方法二&#xff1a;映射网络驱动器背景描述 公司发的新电脑&#xff0c;只有普通用户权限&#xff0c;所以可想而知磁盘只有一个C盘&#xff0c;但是以前习惯性的将一些软件啥的放在D盘中&#xff0c;所以把C盘…

打好“三场仗”,数据库新晋厂商石原子胜券在握

纵观数字经济时代&#xff0c;数据规模呈爆发式增长&#xff0c;国产化替代加速发展。据中国信通院《数据库发展研究报告(2021年)》预测&#xff0c;预计到2025年&#xff0c;全球数据库市场规模将达到798亿美元&#xff0c;其中&#xff0c;中国数据库市场总规模将达到688亿元…