当前位置:网站首页>堆内存的介绍及应用(含例子)
堆内存的介绍及应用(含例子)
2022-08-01 09:12:00 【吃瓜的三木】
一、什么是堆内存
是进程的一个内存段(text\data\bss\heap\stack),由程序员手动管理
优点:足够大,
缺点:使用麻烦
二、为什么要使用堆内存
1、随着程序的复杂,数据量变多
2、其它内存的申请、释放不受控制,堆内存的申请、释放受控制,可以适时的节约内存
三、如何使用堆内存
注意:C语言中没有控制堆内存的语句,只能使用C标准库中的函数
#include<stdlib.h>
- 例如:void *malloc(size_t size);
功能:从堆内存中申请size个字节的内存,申请到内存中数据的值不确定
返回值:成功返回申请到的连续内存的首地址,失败返回NULL - void free(void ptr);
功能:释放一块堆内存 ptr: 要释放的堆内存的首地址 注意:free释放只是使用权,数据不会全部清理 不能连续释放,但是可以释放NULL - void *calloc(size_t nmemb,size_t size);
功能:从堆内存申请nmemb块,每块size字节大小的内存 返回值:成功返回申请到的连续内存的首地址,失败返回NULL
注意:calloc申请到的内存会被初始化为0,速度比malloc慢 short *p = calloc(10,4) == malloc(40) - void realloc(void *ptr,size_t size);
功能:改变已有的堆内存的大小,size表示调整后的大小,在原有的基础上调大调小
返回值:调整后内存块的首地址,一定要重新接受返回值,可能不是在原位置进行调整 如果无法在原位置调整:
1.申请一块新的符合大小的内存
2.拷贝原内存中的数据
3.释放原内存,返回新内存首地址
四、malloc的内存管理机制
- 当首次向malloc申请内存,malloc会向操作系统申请内存,操作系统会直接分配33页(1页=4096字节)内存
malloc管理,但是并不意味着可以越界访问,因为malloc可能把其它的内存分配给‘其他人’,这样就会产生脏数据 - 每个内存块之间会有空隙(4~12字节),一部分空隙是为了内存对齐,其中一定有4字节记录了malloc的维护信息,这些维护信息决定了下一次malloc分配内存的位置,如果破坏了维护信息,会影响下一次malloc或者free的过程
五、使用堆内存需要注意的问题
内存泄漏:
内存无法在使用,也无法被释放,需要再次使用时只能重新申请内存,然后继续重复以上过程,日积月累后可用的内存越来越少
注意:一旦进程结束,属于该进程的所有资源都会被操作系统回收
如何尽量的减少内存泄漏:谁申请谁释放,谁知道该释放谁释放
如何判断、定位内存泄漏
1、查看内存使用情况
win 任务管理器
Linux ps -aux命令
2、借助代码分析工具 mtrace 检查malloc和free是否成对出现
3、封装malloc、free,记录申请、释放的信息到日记文件中
void *m_malloc(size_t size)
{
s = malloc(size);
fprintf("h%d malloc",filename);
}
void m_free(void *ptr)
{
free(ptr);
}
内存碎片:
已经释放了但无法继续使用的内存叫做内存碎片,它是由于申请和释放的时间不协调导致的,无法完全避免,只能尽量减少
如何减少内存碎片的产生:
1、尽量使用栈内存
2、不要频繁地申请、释放内存
3、尽量申请大块内存,自己来管理
六、内存清理函数
#include<stdio.h>
void bzero(void *s,size_t n);
功能:把一块内存清理为0
s;内存块的首字节
n:内存块的字节数
#include<string.h>
void *memset(void *s,int c,size_t n);
功能:把内存块按字节设置为c
s:内存块的首地址
c:想要设置ASCII值
n:内存块的字节数
返回值:成功设置后的内存首地址
七、堆内存定义二位数组
指针数组:
定义n行,m列二维数组
inr arr[10];
for(int i=0;i<n;i++)
{
arr[i] = malloc(msizeof(类型));
}
注意:每一行的m值可以不同,这种方式可以定义不规则的二维数组
优点:可以不规则、对内存要求较低
缺点:申请麻烦、容易产生内存碎片
数组指针
类型 (*arrp)[n] = malloc(sizeof(类型)nm);
申请m行n列的二维数组
缺点:对连续内存要求高,可能申请失败
优点:申请简单
注意:所谓的多维数组,其实都是用一维数组模拟
例子1:计算100~10000之间所有的素数,结果储存在堆内存中,尽量不要浪费内存
1、先计算有多少个、再一下全部申请出来
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<stdbool.h>
4 bool math_is(int n);
5
6 int main()
7 {
8 int *s = NULL;//置空
9 int cnt = 0;
10 for(int i=100;i<=10000;i++)
11 {
12 if(math_is(i))//调用函数,判断是否是素数
13 {
14 cnt++;
15 }
16 }
17 s = malloc(4*cnt);
18 int j = 0;
19 for(int i=100;i<=10000;i++)
20 {
21
22 if(math_is(i))
23 {
24 s[j] = i;
25 j++;
26 }
27 }
28 for(int i=0;i<cnt;i++)
29 {
30 printf("%d ",s[i]);
31 }
32 return 0;
33 }
34
35 bool math_is(int n)
36 {
37
38 for(int j=2;j<=n/2;j++)
39 {
40 if(n%j == 0)
41 {
42 return false;
43 }
44 }
45 return true;
46
47 }
2、一边算,一边申请
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
bool is_prime(int num)
{
for(int i=2;i<=num/2;i++)
{
if(0 == num%i)return false;
}
}
int main()
{
int *arr = NULL;
for(int i=100;i<=10000;i++)
{
if(is_prime(i))
{
arr = realloc(arr,sizeof(int)*(cnt+1));
arr[cnt++] = i;
}
}
}
for(int i=0;i<cnt;i++)
{
printf("%d",arr[i]);
}
边栏推荐
- 华为深度学习课程第六、七章
- 安装GBase 8c数据库的时候,报错显示“Resource,如何解决?
- flink sql-client,怎么处理源端与目标增加端,sql-client包括映射表与JOB如
- GBase 8c中怎么查询数据库配置参数,例如datestyle
- [Dataset] Dataset summary of various insulators, bird's nests and anti-vibration hammers
- UXDB如何返回当前数据库所有表的记录数?
- leetcode-6133:分组的最大数量
- Pod环境变量和initContainer
- HoloView--Customization
- 如何保证数据库与缓存数据一致性?
猜你喜欢

Redis中间件(从搭建到弃坑)

net stop/start mysql80 拒绝访问

Analysis of High Availability Solution Based on MySql, Redis, Mq, ES

HoloView -- Tabular Datasets

various network protocols

HoloView——实时数据
![[Dataset] Dataset summary of various insulators, bird's nests and anti-vibration hammers](/img/02/927f4e228eb3abbd76cade5be00352.png)
[Dataset] Dataset summary of various insulators, bird's nests and anti-vibration hammers

Redis middleware (from building to refuse pit)

Prime Ring Problem(素数环问题)

XX市消防救援指挥中心实战指挥平台多链路聚合解决方案实例
随机推荐
The soul asks: How does MySQL solve phantom reads?
mysql查看cpu使用情况
[Tear AHB-APB Bridge by hand]~ Why aren't the lower two bits of the AHB address bus used to represent the address?
The socket option
最新的Cesium和Three的整合方法(附完整代码)
[Interview: Concurrency 39: Multithreading: Thread Pool] ThreadPoolExecutor Class - Submit, Stop
Do I need to introduce any dependencies to write data to clickhouse using flinksql?
How to get page data
How does UXDB return the number of records for all tables in the current database?
In the background of the GBase 8c database, what command is used to perform the master-slave switchover operation for the gtm and dn nodes
自定义IP在PCIE中使用
Delphi MDI appliction documents maximize display, remove buttons such as maximize and minimize
套接字选项
Redis middleware (from building to refuse pit)
sql server, FULL模式, dbcc shrinkfile(2,1) 不能收缩事务日志,还是原来的大小,是为什么?
灵魂发问:MySQL是如何解决幻读的?
zip package all files in the directory (including hidden files/folders)
ASP.NET Core 6框架揭秘实例演示[30]:利用路由开发REST API
华为深度学习课程第九章——卷积神经网络以及案例实践
Classify GBase 8 s lock