【C语言提升】深入了解动态内存管理

news2024/11/26 12:45:04

目录

一、静态分配和动态分配 

二、内存管理函数

1、malloc 申请堆区空间

2、calloc 申请堆区空间

3、free回收堆区空间权限

4、memset内存设置函数

5、realloc内存增减函数

三、内存泄漏(了解)


一、静态分配和动态分配 

1、静态分配

在程序编译或运行过程中,按事先规定大小分配内存空间的分配方式。如int a [10]

必须事先知道所需空间的大小。

分配在栈区或全局变量区,一般以数组的形式。

2、动态分配

在程序运行过程中,根据需要大小自由分配所需空间。

按需分配。
分配在堆区,一般使用特定的函数进行分配。

二、内存管理函数

        C语言提供了一些内存管理函数,用以按需动态分配与回收内存空间。

1、malloc 申请堆区空间

        在内存的动态存储区(堆区)中分配一块长度为size字节的连续区域,用来存放类型说明符指定的类型。函数原型返回void*指针,使用时必须做相应的强制类型转换,分配的内存空间内容不确定,一般使用memset初始化

头文件:#include<stdlib.h>

用法:void *malloc(size_t size);//size表示申请的空间字节数,void *(万能指针)

函数的返回值成功返回空间起始地址

                      失败:NULL

特点:malloc申请的堆区空间 需要使用memset对原有内容清0,即不自动清0

2、calloc 申请堆区空间

头文件:#include<stdio.h>

用法:void *calloc(size_t nmemb, size_t size);

nmemb:内存的块数

size:每一块的字节数

函数返回值成功返回堆区空间起始地址

           失败:为NULL

calloc会对申请的空间 自动清0

3、free回收堆区空间权限

头文件:#include<stdlib.h>

用法:void free(void *ptr);

ptr为需要释放的堆区空间的起始地址

若未用free回收空间,进程结束会全部申请的空间会被回收。

实际应用举例:申请n个元素的动态数组

malloc(n*sizeof(int));

calloc(n, sizeof(int));

综合案例分析: 

4、memset内存设置函数

头文件:#include<string.h>

用法:void *memset(void *s, int c, size_t n);

s是空间的起始地址

c是空间中每个字节填充的值

n是空间的字节宽度

案例:动态数组

#include <stdio.h>
#include<stdlib.h>
#include<string.h>
void test()
{	
	int n = 0;
	printf("请输入元素个数:");
	scanf("%d", &n);
	int *p = NULL;
	p=(int *)malloc(n*sizeof(int));
	if (p = NULL)
	{
		return;
	}
	//将申请的堆区空间清0
	memset(p, 0, n * sizeof(int));
	int i=0;
	for ( i = 0; i < n; i++)
	{
		scanf("%d", p + i);
	}
	for ( i = 0; i < n; i++)
	{
		printf("%d ", p[i]);//*(p+i);
	}
	free(p);
	return;
}
int main(int argc, char const* argv[])
{
		test();
		return 0;
}

5、realloc内存增减函数

        在原先s指向的内存基础上重新申请内存,新的内存的大小为size个字节
如果原先内存后面有足够大的空间,就追加,如果后边的内存不够用,则relloc函数会在堆区
找一个size个字节大小的内存申请,将原先内存中的内容拷贝过来,然后释放原先的内存,最后返回新内存的地址

头文件:#include<stdlib.h>

用法:void *realloc(void *ptr, size_t size);

ptr为旧空间起始地址
size为旧空间大小加新空间大小
返回值为增减空间后整个空间的起始地址

注:必须使用指针变量获取realloc返回值,p=realloc(p,20+20);

#include <stdio.h>
#include<stdlib.h>
void test04()
{
int n = 0;
printf("输入int元素的个数:");
scanf("%d", &n);
//根据元素的个数申请空间
int *p = NULL;
p = (int *)calloc(n, sizeof(int));
if (p == NULL)
{
    return;
}
//获取键盘输入
int i = 0;
for (i = 0; i < n; i++)
{
    scanf("%d", p + i);
}
//遍历数组元素
for (i = 0; i < n; i++)
{
    printf("%d ", p[i]); //*(p+i)
}
printf("\n");
printf("输入新增的元素个数:");
int new_n = 0;
scanf("%d", &new_n);
//追加空间
p = (int *)realloc(p, (n + new_n) * sizeof(int));
printf("输入%d个新增元素:", new_n);
//输入新增的元素
for (i = n; i < n + new_n; i++)
{
    scanf("%d", p + i);
}
//遍历数组元素
for (i = 0; i < n + new_n; i++)
{
    printf("%d ", p[i]); //*(p+i)
}
printf("\n");
free(p);
}

三、内存泄漏(了解)

        申请的内存,首地址丢了,无法再使用,也没法释放,这块内存就被泄露了。

案例1:

char *p;

p=(char *)malloc(100);

p="hello world";//p 指向别的地方了

//此后,找不到申请的 100 个字节,动态申请的 100 个字节就被泄露了。

案例2:

void test()
{
    char *p;
    p=(char *)malloc(100);
    //函数结束该内存未释放
}
int main()
{
    test();
    test();//调用一次,内存就泄漏一次。
}

 案例2解决方案:调用结束时用free函数释放内存或者将指针变量返回

free函数释放:

void test()
{
    char *p;
    p=(char *)malloc(100);
    //函数结束该内存未释放
    ...
    free(p);
}
int main()
{
    test();
}

 指针变量返回:

void test()
{
    char *p;
    p=(char *)malloc(100);
    //函数结束该内存未释放
    ...
    return p;
}
int main()
{
    char *q;
    q=test();
    /调用一次,内存就泄漏一次。
}

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

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

相关文章

【Python】类型注解 ② ( 基础变量设置类型注解 | 类对象设置类型注解 | 容器变量设置简易类型注解 | 容器变量设置详细类型注解 )

文章目录 一、为变量设置类型类型注解1、变量设置 " 类型注解 " 语法2、为 基础类型变量 设置 " 类型注解 "3、为 类 的 对象类型 设置 " 类型注解 "4、为 基础容器类型变量 设置 简易 " 类型注解 "5、为 基础容器类型变量 设置 详细 …

gma 2 教程(二)数据操作:3. 支持生成的栅格格式信息

为了方便了解和选择输出栅格格式、配置高级创建选项&#xff0c;下表列出了gma可以生成&#xff08;复制/创建/转换&#xff09;的所有栅格格式的主要信息&#xff1a; 格式名生成模式支持数据类型扩展名多维栅格支持色彩映射表支持的数据类型多波段支持压缩模式AAIGrid复制By…

Redis学习(三)分布式缓存、多级缓存、Redis实战经验、Redis底层原理

文章目录 分布式缓存Redis持久化RDB持久化AOF持久化 Redis主从Redis数据同步原理全量同步增量同步 Redis哨兵哨兵的作用和原理sentinel&#xff08;哨兵&#xff09;的三个作用是什么&#xff1f;sentinel如何判断一个Redis实例是否健康&#xff1f;master出现故障后&#xff0…

Java-API简析_java.lang.ProcessBuilder类(基于 Latest JDK)(浅析源码)

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/131729933 出自【进步*于辰的博客】 因为我发现目前&#xff0c;我对Java-API的学习意识比较薄弱…

echarts_柱状图+漏斗图

目录 柱状图(bar)需求[1] 复制案例[2] 修改类目轴方向[3] 修改数据渲染方向[4] 修改坐标轴文本样式 漏斗图(funnel)漏斗图的形状 柱状图(bar) 需求 如上图&#xff0c;做一个横向柱状图&#xff0c;后端返回的数据是从小向大排列的数据&#xff0c;希望能够按照顺序进行展示。…

pnpm安装方式

pnpm安装方式 要使用pnpm进行安装&#xff0c;首先需要确保已经安装了Node.js。然后&#xff0c;按照以下步骤进行pnpm的安装&#xff1a; 打开终端或命令提示符。 在命令行中输入以下命令来全局安装pnpm&#xff1a; npm install -g pnpm这将使用npm将pnpm包全局安装到您的…

WireShark

文章目录 IP协议部分协议对应协议号路由器IP分片IP分片的缺点 TCP协议[TCP MSS](https://blog.csdn.net/meihualing/article/details/113739693) UDP协议ARP ICMPDHCPDNSFTP wireshark可以学习网络协议&#xff0c;解决一些问题 IP协议 IP指网际互连协议&#xff0c;Internet P…

动态规划01背包之1049 最后一块石头的重量 II(第9道)

题目&#xff1a; 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 。那么粉碎的可能结果如下&#xff1a; …

Verilog 学习之路

循环 7-10 代码段 generategenvar i;for (i0; i<8; i i1) begin: my_block_nameassign out[i] in[8-i-1];end endgenerate解释 该代码使用了 S y s t e m V e r i l o g SystemVerilog SystemVerilog 中的 g e n e r a t e generate generate 构造&#xff0c;它允许在…

【Docker】快速入门,带你快速了解 Docker

文章底部有投票活动&#xff0c;赶快参与进来吧&#x1f603; 相信大家在开发过程中都听说过 Docker 一词&#xff0c;至于 Docker 在开发中扮演的角色&#xff0c;估计好多人都说不上来&#xff0c;今天就让阿Q带大家一起揭开它神秘的面纱&#xff01; 文章目录 什么是容器&a…

【C++初阶】C++入门——内联函数、auto、范围for、nullptr

文章目录 一、内联函数1.1 定义1.2 特性 二、auto关键字2.1 简介2.2 auto使用细则2.3 不能使用auto的场景 三、基于范围的for循环3.1 范围for的使用条件 四、指针空值nullptr 一、内联函数 普通的函数在调用的时候会开辟函数栈帧&#xff0c;会产生一定量的消耗&#xff0c;在C…

《算法竞赛·快冲300题》每日一题:“推箱子”

《算法竞赛快冲300题》将于2024年出版&#xff0c;是《算法竞赛》的辅助练习册。 所有题目放在自建的OJ New Online Judge。 用C/C、Java、Python三种语言给出代码&#xff0c;以中低档题为主&#xff0c;适合入门、进阶。 文章目录 题目描述题解C代码Java代码Python代码 “ 推…

1 考试宝自建题库使用说明

注意&#xff1a; 标准格式&#xff1a;括号里不写对象&#xff0c;然后答案行数另取一行&#xff0c;放在选项后一行也是可以的&#xff0c;选项可以横排或者竖排。横排的话选项要用空格隔开&#xff0c;选项的ABCD要加"."&#xff0c;如A. B. C. D. 1. 法治中国…

多个电源模块带电感,给一个负载用的直流压降仿真-CORE电源

多个电源模块带电感,给一个负载用的直流压降仿真-CORE电源 下面介绍如何对多个电源模块带电感,给一个负载用的直流压降仿真,常见于CPU的CORE电源。以下图为例 具体操作步骤如下 设置VRAM(因为是多个电源输出,所以每个电源都要设置成VRAM)

【C语言】轻松模拟实现qsort函数

君兮_的个人主页 勤时当勉励 岁月不待人 C/C 游戏开发 Hello,米娜桑们&#xff0c;这里是君兮_&#xff0c;我们今天接着上回更新的内容&#xff0c;讲讲我们如何模拟实现自己的qsort函数&#xff0c; 废话不多说&#xff0c;我们开始今天的内容。 模拟实现qsort函数 qsort函…

文心一言 VS 讯飞星火 VS chatgpt (59)-- 算法导论6.4 3题

文心一言 VS 讯飞星火 VS chatgpt &#xff08;59&#xff09;-- 算法导论6.4 3题 三、对于一个按升序排列的包含 n 个元素的有序数组 A 来说&#xff0c;HEAPSORT 的时间复杂度是多少?如果 A 是降序呢? 文心一言&#xff1a; 对于一个按升序排列的包含 n 个元素的有序数组…

ModaHub魔搭社区:AI原生云向量数据库Weaviate 对比 Milvus

通过以下一系列能力比较 Weaviate 对比 Milvus。我们希望您选择适合您的最佳开源数据库,即使它不是我们。 Weaviate 与 Milvus 可扩展性对比 Weaviate Milvus 计算存储分离 ❌ ✔️ 支持 10 亿级向量数据 ❌ ✔️ 云原生 ✔️ ✔️ 多副本 ✔️ ✔️ 查询插入分离

第一次用用Opencv进行图像处理

2023.7.06更新 codeblocks安装opencv 直接放参考链接&#xff0c;完成安装该步骤来&#xff0c;简单高效&#xff01; 安装教程链接 有一个问题就是第一次安装完成后运行时会报确实某些ddl的错误&#xff0c;关机重启就好啦&#xff01; 尝试运行 ddl的错误解决后可以用以…

用Python采用Modbus-Tcp的方式读取PLC模块数据

使用计算器得到需要的寄存器地址 这里PLC地址是83,对应的程序16进制读取地址是53 实际上由于PLC地址从1开始&#xff0c;所以这里实际地址应该是52&#xff0c;因为计算机从0开始 使用网络调试助手生成报文 使用Python中的内置函数int()。以下是将人员卡号’b’3b44’转换为十…

mac批量提取文件夹的名称,怎么操作?

mac批量提取文件夹的名称&#xff0c;怎么操作&#xff1f;很多小伙伴想知道在mac电脑上可以一键快速批量的将大量文件夹的名提取出来&#xff0c;而不是采用一个一个名称提取的方法&#xff0c;这是一个有利于提高工作效率的办法&#xff0c;这一项技能在网上几乎找不到解决办…