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

C【动态内存管理】

1. 为什么存在动态内存分配

int val = 20;//在栈空间上开辟四个字节
char arr[10] = {0};//在栈空间上开辟10个字节的连续空间

2. 动态内存函数的介绍

2.1 malloc:stdlib.h

void* malloc (size_t size);
int* p = (int*)malloc(40);

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>int main()
{//向内存申请10个整形的空间int* p = (int*)malloc(40);if (p == NULL){//打印错误原因的一个方式printf("%s\n", strerror(errno));}else{//正常使用空间int i = 0;for (i = 0; i < 10; i++){*(p + i) = i;}for (i = 0; i < 10; i++){printf("%d ", *(p + i));}}//当动态申请的空间不再使用的时候//就应该还给操作系统free(p);//上面是将p断开,但是实际上p还是存储内容,所以我们手动设置为nullp = NULL;return 0;
}

2.2 free:stdlib.h

是用来做动态内存的释放和回收的

注意点:free(str)后,实际上str还执行一个空的地址,所以此时str!=NULL

void free (void* ptr);

2.3 calloc

calloc 函数也用来动态内存分配。可以初始化空间。

void* calloc (size_t num, size_t size);
int*p = (int*)calloc(10, sizeof(int));
int main()
{//malloc(10*sizeof(int))int*p = (int*)calloc(10, sizeof(int));if (p == NULL){printf("%s\n", strerror(errno));}else{int i = 0;for (i = 0; i < 10; i++){printf("%d ", *(p + i));}}//释放空间//free函数是用来释放动态开辟的空间的free(p);p = NULL;return 0;
}

2.4 realloc

当初始申请空间不够,这时使用realloc开辟新的空间【调整动态开辟内存空间的大小】

使用注意点:

1. 如果p指向的空间之后有足够的内存空间可以追加,则直接追加,后返回p
2. 如果p指向的空间之后没有足够的内存空间可以追加,则realloc函数会重新找一个新的内存区域
开辟一块满足需求的空间,并且把原来内存中的数据拷贝回来,释放旧的内存空间
最后返回新开辟的内存空间地址
3. 得用一个新的变量来接受realloc函数的返回值

void* realloc (void* ptr, size_t size);

#include <stdio.h>
int main()
{int *ptr = (int*)malloc(100);if(ptr != NULL){//业务处理}else{exit(EXIT_FAILURE);    }//扩展容量//代码1ptr = (int*)realloc(ptr, 1000);//这样可以吗?(如果申请失败会如何?)//代码2int*p = NULL;p = realloc(ptr, 1000);if(p != NULL){ptr = p;}//业务处理free(ptr);return 0;
}

3. 常见的动态内存错误

3.1 对NULL指针的解引用操作

//1. 对NULL进行解引用操作int *p = (int*)malloc(40);//万一malloc失败了,p就被赋值为NULL//所以我们在申请完一块空间之后,一定要进行判空操作*p = 0;//errint i = 0;for (i = 0; i < 10; i++){*(p + i) = i;//err}free(p);p = NULL;

3.2 对动态开辟空间的越界访问

//2. 对动态开辟的内存的越界访问int *p = (int*)malloc(5 * sizeof(int));if (p == NULL){return 0;}else{int i = 0;for (i = 0; i < 10; i++){*(p + i) = i;}}//free(p);p = NULL;

3.3 对非动态开辟内存使用free释放

//栈区开辟出来的,不是动态开辟int a = 10;int* p = &a;*p = 20;//3. 对非动态开辟内存的freefree(p);p = NULL;return 0;

3.4 使用free释放一块动态开辟内存的一部分

int*p = (int*)malloc(40);if (p == NULL){return 0;}int i = 0;for (i = 0; i < 5; i++){*p++ = i;}//回收空间// 使用free释放动态开辟内存的一部分free(p);p =NULL;

3.5 对同一块动态内存多次释放

int *p = (int*)malloc(40);if (p == NULL){return 0;}//使用//释放free(p);//将p设置为空指针,可以防止重复释放产生的错误p = NULL;

3.6 动态开辟内存忘记释放(内存泄漏)

while (1){malloc(1);}

4. 几个经典的笔试题

4.1 题目1:

//面试1:
void GetMemory(char *p)
{p = (char *)malloc(100);
}void Test(void)
{char *str = NULL;GetMemory(str);strcpy(str, "hello world");printf(str);
}int main()
{Test();char*str = "abcdef";printf("%s\n", str);printf(str);printf("abcdef");return 0;
}

修改结果

void GetMemory(char **p)//**p:是p的地址
{//*p:是p的内容*p = (char *)malloc(100);
}void Test(void)
{char *str = NULL;GetMemory(&str);//传地址strcpy(str, "hello world");printf(str);free(str);str = NULL;
}int main()
{Test();return 0;
}
char* GetMemory(char *p)
{p = (char *)malloc(100);//将p传递除去return p;
}void Test(void)
{char *str = NULL;str = GetMemory(str);strcpy(str, "hello world");printf(str);free(str);str = NULL;
}int main()
{Test();return 0;
}

4.2 题目2:

​​​​​​​

【存储在栈区中的数据,出了函数则就会被销毁】

//面试2
char *GetMemory(void)
{char p[] = "hello world";//局部变量//跳出此函数,则p被销毁return p;
}void Test(void)
{char *str = NULL;str = GetMemory();//此时str的p的地址printf(str);//非法地址访问,故输出随机值
}int main()
{Test();return 0;
}

【数据存储在静态区(static),出了函数数据还是存在】

//在静态区,出了函数还是可以继续使用
int* test()
{//使用static,将a放入静态区,出了这个函数,内存并没有被销毁,故在外面还可以访问到static int a = 10;//静态区int a = 10;//栈区 return &a;
}int main()
{int*p = test();//此时p接收到a的地址*p = 20;//将a修改为20return 0;//20
}

【数据存储在堆区,出了函数数据还是存在】

//在堆区,出函数还是存在
int* test()
{int *ptr = malloc(100);//堆区return ptr;
}int main()
{int *p = test();return 0;
}

4.3 题目3:

void GetMemory(char **p, int num)
{*p = (char *)malloc(num);//给p创建100个新的char
}
void Test(void)
{char *str = NULL;GetMemory(&str, 100);strcpy(str, "hello");//可以输出printf(str);//改:忘记free内容,导致内存泄露free(str);str = NULL;
}

4.4 题目4:

void Test(void)
{char *str = (char *)malloc(100);strcpy(str, "hello");free(str);//free了但是没有把指针置为null//此处的问题:已经释放的空间,还被使用if (str != NULL)//则此时str还不为NUll,则进入判断{strcpy(str, "world");printf(str);}
}int main()
{Test();//worldreturn 0;
}

解决:

void Test(void)
{char* str = (char*)malloc(100);strcpy(str, "hello");free(str);//解决:将str置为NULLstr = NULL;if (str != NULL){strcpy(str, "world");printf(str);}
}int main()
{Test();//worldreturn 0;
}

5. C/C++程序的内存开辟

C/C++程序内存分配的几个区域:

1. 栈区(stack):在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结 束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是 分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返 回地址等。

2. 堆区(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。分 配方式类似于链表。

3. 数据段(静态区)(static)存放全局变量、静态数据。程序结束后由系统释放。

4. 代码段:存放函数体(类成员函数和全局函数)的二进制代码。

6. 柔性数组

结构中的最后一个元素允许是未知大小的数组,这就叫做『柔性数组』成员。

struct S
{int n;int arr[10];
};struct S
{int n;int arr[];//未知大小的
};struct S
{int n;int arr[0];//未知大小的-柔性数组成员-数组的大小是可以调整的
};

6.1 柔性数组的特点:

  • 结构中的柔性数组成员前面必须至少一个其他成员。
  • sizeof 返回的这种结构大小不包括柔性数组的内存。
  • 包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大 小,以适应柔性数组的预期大小。
//代码1
int i = 0;
type_a *p = (type_a*)malloc(sizeof(type_a)+100*sizeof(int));
//业务处理
p->i = 100;
for(i=0; i<100; i++)
{p->a[i] = i;
}
free(p);

6.2 柔性数组的使用--int[] a

struct S
{int n;int arr[0];//未知大小的-柔性数组成员-数组的大小是可以调整的
};int main()
{struct S s;printf("%d\n", sizeof(s));////sizeof(struct S):不包括int arr的大小//5*sizeof(int):手动的给arr赋值struct S* ps = (struct S*)malloc(sizeof(struct S)+5*sizeof(int));ps->n = 100;int i = 0;for (i = 0; i < 5; i++){ps->arr[i] = i;//0 1 2 3 4}//开辟内存struct S* ptr = realloc(ps, 44);if (ptr != NULL){ps = ptr;}for (i = 5; i < 10; i++){ps->arr[i] = i;}//打印arr所有数值for (i = 0; i < 10; i++){printf("%d ", ps->arr[i]);}//释放free(ps);ps = NULL;return 0;
}

6.3 柔性数组的扩展:int* arr

struct S
{int n;int* arr;
};
int main()
{//sizeof(struct S):此时包括int* arrstruct S* ps = (struct S*)malloc(sizeof(struct S));//再一次给arr创建动态内存ps->arr = malloc(5 * sizeof(int));int i = 0;for (i = 0; i < 5; i++){ps->arr[i] = i;}for (i = 0; i < 5; i++){printf("%d ", ps->arr[i]);}//调整大小int* ptr = realloc(ps->arr, 10 * sizeof(int));if (ptr != NULL){ps->arr = ptr;}for (i = 5; i < 10; i++){ps->arr[i] = i;}for (i = 0; i < 10; i++){printf("%d ", ps->arr[i]);}//释放内存:注意释放顺序free(ps->arr);ps->arr = NULL;free(ps);ps = NULL;return 0;
}

6.4 int arr[0] 和 int* arr的区别

上述 代码1 和 代码2 可以完成同样的功能,但是 方法1 的实现有两个好处:

​​​​​​​

相关文章:

C【动态内存管理】

1. 为什么存在动态内存分配 int val 20;//在栈空间上开辟四个字节 char arr[10] {0};//在栈空间上开辟10个字节的连续空间 2. 动态内存函数的介绍 2.1 malloc&#xff1a;stdlib.h void* malloc (size_t size); int* p (int*)malloc(40); #include <stdlib.h> #incl…...

Javase | 集合-上

目录&#xff1a; 一、集合&#xff1a;1.集合的概述2.集合的分类 二、“单个方式”存储元素&#xff1a;1.Collection1.1 Collection的概述1.2 Collection接口中常用的方法Iterator<T> iterator( ) 1.3 Collection下的子接口 2.Iterable&#xff1a;2.1 Iterable的概述2…...

Multitor:一款带有负载均衡功能的多Tor实例创建工具

关于Multitor Multitor是一款带有负载均衡功能的多Tor实例创建工具&#xff0c;Multitor的主要目的是以最快的速度完成大量Tor进程的初始化&#xff0c;并将大量实例应用到我们日常使用的程序中&#xff0c;例如Web浏览器和聊天工具等等。除此之外&#xff0c;在该工具的帮助下…...

AIGC专栏6——通过阿里云与AutoDL快速拉起Stable Diffusion和EasyPhoto

AIGC专栏6——通过阿里云与AutoDL快速拉起Stable Diffusion和EasyPhoto 学习前言Aliyun DSW快速拉起&#xff08;新用户有三个月免费时间&#xff09;1、拉起DSW2、运行Notebook3、一些小bug AutoDL快速拉起1、拉起AutoDL2、运行Notebook 学习前言 快速拉起AIGC服务 对 用户体…...

Mysql的逻辑架构、存储引擎

1. 逻辑架构剖析 1.1 服务器处理客户端请求 首先MySQL是典型的C/S架构&#xff0c;即Clinet/Server 架构&#xff0c;服务端程序使用的mysqld。 不论客户端进程和服务器进程是采用哪种方式进行通信&#xff0c;最后实现的效果是&#xff1a;客户端进程向服务器进程发送一段文…...

[ES6]模块

[ES6]模块 特点export 与 import基本用法导入导出基本方式导入导出等价方式html 导入 别名导出默认导出基本用法默认导出对象 复合使用import 命令的特点只读属性单例模式静态执行特性 在 ES6 前&#xff0c; 实现模块化使用的是 RequireJS 或者 seaJS(分别是基于 AMD 规范的模…...

物联网终端算法

物联网终端算法是指在物联网终端设备上运行的各种算法&#xff0c;包括数据采集、数据预处理、数据传输、数据存储、数据处理、数据分析等算法。以下是物联网终端算法的一些具体应用&#xff1a; 数据采集算法&#xff1a;用于采集各种传感器数据&#xff0c;包括温度、湿度、气…...

【面试刷题】——TCP三次握手,以及为什么要三次握手

TCP&#xff08;传输控制协议&#xff09;的三次握手是建立TCP连接的过程&#xff0c;它确保了通信双方的正常启动和参数协商。三次握手的过程如下&#xff1a; 客户端发送请求&#xff1a; 客户端首先向服务器发送一个特殊的TCP报文&#xff0c;称为SYN&#xff08;同步&…...

算法系列-力扣206-单链表反转

题目说明 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 方法一&#xff1a;头插法反转链表 思路&#xff1a; 声明p指针指向原头节点&#xff0c;并将头节点置空&#xff1b;p指针循环原链表将元素用头节点插入法逐个插入head中&…...

网络基础-应用层协议-HTTP/HTTPS

HTTP/HTTPS HTTP基本概念协议格式请求报文请求方法请求资源地址协议版本 应答报文 常见Header常见状态码与状态描述Cookie&Sessionhttp协议特点 HTTPS基本概念对称加密与非对称加密数据摘要&数据指纹HTTPS工作过程探究只采用对称加密只采用非对称加密双方都采用非对称加…...

problen(5)ubuntu版本问题

浅浅记录一下这段时间的血和泪吧&#xff0c;大概耗时快一个月了吧&#xff0c;终于解决了...... 因为需要开启pwn之旅&#xff0c;需要在Ubuntu上安装一些东西&#xff0c;就是下面的一条命令&#xff1a; sudo pip3 install pwntools -i Simple Index&#xff08;显示不太好了…...

写一篇nginx配置指南

nginx.conf配置 找到Nginx的安装目录下的nginx.conf文件&#xff0c;该文件负责Nginx的基础功能配置。 配置文件概述 Nginx的主配置文件(conf/nginx.conf)按以下结构组织&#xff1a; 配置块功能描述全局块与Nginx运行相关的全局设置events块与网络连接有关的设置http块代理…...

rhel8防火墙firewalld操作

1.查看默认区域 [rootlocalhost r]# firewall-cmd --get-default-zone public2.查看网卡关联的区域 [rootlocalhost r]# firewall-cmd --get-zone-of-interfaceifcfg-ens160 external 3.设置网卡的默认区域修改为work [rootlocalhost r]# firewall-cmd --zonework --change…...

OpenCV项目实战(2)— 如何用OpenCV实现弹球动画

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。OpenCV能够在画布上绘制静态的图形&#xff0c;例如&#xff0c;线段、矩形、正方形、圆形、多边形、文字等。那么&#xff0c;能不能让这些静态的图形移动起来&#xff1f;如果能&#xff0c;又该如何编写代码呢&#xff…...

golang iris框架 + linux后端运行

go mod init myappgo get github.com/kataras/iris/v12latestpackage mainimport "github.com/kataras/iris/v12"func main(){app : iris.New()app.Listen(":port") }打包应用 go build main.go开启服务 #nohup ./程序名称 nohup ./main关闭后台 #ps -e…...

linux shell操作- 02 常用命令及案例

文章目录 常用命令 续 常用命令 续 定时任务 通过文本编辑cron任务&#xff0c;实现定时操作 分 小时 天 月 星期 绝对路径sh or cmd* 表示每个xxx&#xff0c;如每个小时每小时的第三分钟执行cmd-> 03 * * * * /home/lauf/scraw.sh每天的第5、8个小时执行-> 00 5,8 * *…...

考研408 | 【计算机组成原理】 数据的表示和运算

进位计数制 十进制计数法&#xff1a; 推广&#xff1a;r进制计数法 任意进制-->十进制&#xff1a; 二进制<-->八进制、十六进制&#xff1a; 各种进制的常见书写方式&#xff1a; 十进制-->任意进制&#xff1a; 十进制-->二进制&#xff08;拼凑法&#xff…...

【小沐学NLP】AI辅助编程工具汇总

文章目录 1、简介2、国内2.1 aiXcoder2.1.1 工具特点2.1.2 部署方式2.1.3 使用费用2.1.4 代码测试2.1.4.1 代码搜索引擎2.1.4.2 在线体验 2.2 CodeGeeX2.2.1 工具特点2.2.2 部署方式2.2.3 使用费用2.2.4 代码测试 2.3 Alibaba Cloud AI Coding Assistant&#xff08;cosy&#…...

linux动态扩容系统盘(非lvm磁盘)

查看磁盘状态 执行df -Th查看磁盘情况 [rootiotdbtest1 ~]# df -Th Filesystem Type Size Used Avail Use% Mounted on devtmpfs devtmpfs 7.7G 0 7.7G 0% /dev tmpfs tmpfs 7.7G 0 7.7G 0% /dev/shm tmpfs tmpfs …...

Gitlab仓库部署

Gitlab仓库部署 一、Gitlab的概述1、gitlab介绍2、gitlab主要功能3、gitlab和github的区别 二、部署环境1、安装依赖环境2、安装Postfix邮箱3、Gitlab优势4、Gitlab工作流程 三、Gitlab部署过程1、Yum安装Gitlab2、配置gitlab站点URL3、启动并访问Gitlab 四、Gitlab具体操作1、…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

【JVM面试篇】高频八股汇总——类加载和类加载器

目录 1. 讲一下类加载过程&#xff1f; 2. Java创建对象的过程&#xff1f; 3. 对象的生命周期&#xff1f; 4. 类加载器有哪些&#xff1f; 5. 双亲委派模型的作用&#xff08;好处&#xff09;&#xff1f; 6. 讲一下类的加载和双亲委派原则&#xff1f; 7. 双亲委派模…...