内存管理函数malloc,calloc,realloc详解

简介: 内存管理函数malloc,calloc,realloc详解

1.malloc

当我们想开辟一块动态内存空间的时候,就需要使用动态内存函数了,比如

char* p;

当我们想要使用地址p下的内存时,就需要用到malloc函数

void* malloc(size_t size);

注意,malloc函数的返回类型是(void*),形参是要开辟空间的字节数。所以要使用malloc这个函数,必须将返回值强制类型转换为想要的类型,比如

1. char* p1=(char*)malloc(10);//在p1这个地址下开辟10个字节空间,可以存放10个char型数据
2. int* p2=(int*)malloc(20);//在p2这个地址下开辟20个字节空间,可以存放5个int型数据

注意,malloc函数开辟内存空间有时会开辟失败,这时会返回空指针(NULL),所以,要较好的使用malloc函数,还要检查一下是否成功开辟内存,代码如下

1. int* p=(int*)malloc(20);//开辟内存空间
2. if(p==NULL)
3. {
4. printf("%s",strerror(errno));//打印开辟失败的原因
5. }

需要知道的是,malloc函数开辟的内存空间不会自动初始化,里面放的是随机值

1.  int* p = (int*)malloc(20);//开辟内存空间
2.  if (p == NULL)
3.  {
4.    printf("%s", strerror(errno));//打印开辟失败的原因
5.  }
6.  else
7.  for (int i = 0; i <5 ; i++)//访问新开辟的内存
8.  {
9.    printf("%d", (int)*(p + i));
10.   }

结果如下

malloc函数算是讲完了,但有一个非常重要的点并没有提到。我们知道创建一个数组相当于向内存空间申请了连续的一块空间,数组申请的内存空间是在栈上的,数组离开作用域会自动销毁,释放内存。

但是这里用malloc函数申请的内存空间是在堆上的,出作用域不会销毁,必须手动释放内存,否则会造成内存泄漏!(即使退出程序OS会自动回收内存,还是要有手动释放的好习惯)

手动释放内存需要使用free函数,free函数会把开辟的内存释放,内存的首地址就会变成野指针,所以还要将首地址置为空。代码如下

1. int* p = (int*)malloc(20);//开辟内存空间
2.  if (p == NULL)
3.  {
4.    printf("%s", strerror(errno));//打印开辟失败的原因
5.  }
6. //使用
7. 
8. //手动释放空间
9.  free(p);
10.   p = NULL;

2.calloc

不同于malloc的是,calloc函数会自动将新开辟的内存空间初始化为全0

void* calloc(size_t num,size_t size);

size_t num:开辟的个数

size_t size:开辟的类型大小

例如,开辟5个整型空间

1. #include<stdlib.h>
2. #include<errno.h>
3. #include<string.h>
4. #include<stdio.h>
5. int main()
6. {
7.  int* p = (int*)calloc(5,4);//开辟内存空间
8.  if (p == NULL)
9.  {
10.     printf("%s", strerror(errno));//打印开辟失败的原因
11.   }
12.   else
13.     //使用
14. 
15.   free(p);
16.   p = NULL;
17.   return 0;
18. }
19.

3.realloc

realloc函数用于原开辟的空间不足的情况下开辟更大的空间

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

void* ptr:原空间首地址

size_t size:新空间字节大小

realloc函数开辟新的空间会遇到两种情况

  1. 原空间后面空间充足,在原空间后面继续开辟新的空间,返回的地址和原地址相同。
  2. 原空间后面空间不足:
  • realloc会找到更大的空间
  • 将原来的数据拷贝到新的空间
  • 释放旧的空间
  • 返回新空间的地址(不同于原地址)
1. #include<stdlib.h>
2. #include<errno.h>
3. #include<string.h>
4. #include<stdio.h>
5. int main()
6. {
7.  int* p = (int*)calloc(5,4);//开辟内存空间
8.  if (p == NULL)
9.  {
10.     printf("%s", strerror(errno));//打印开辟失败的原因
11.   }
12.   else
13.     //使用
14.     for (int i = 0; i < 5; i++)
15.     {
16.       printf("%d ", *(p + i));
17.     }
18.   p=realloc(p, 40);//扩大内存空间,将20字节增到40字节
19.   for (int i = 0; i < 10; i++)
20.   {
21.     printf("%d ", *(p + i));
22.   }
23.   free(p);
24.   p = NULL;
25.   return 0;
26. }

 

目录
打赏
0
0
0
0
0
分享
相关文章
【C语言】内存管理函数详细讲解
在C语言编程中,内存管理是至关重要的。动态内存分配函数允许程序在运行时请求和释放内存,这对于处理不确定大小的数据结构至关重要。以下是C语言内存管理函数的详细讲解,包括每个函数的功能、标准格式、示例代码、代码解释及其输出。
122 6
【c语言】字符串函数和内存函数
本文介绍了C语言中常用的字符串函数和内存函数,包括`strlen`、`strcpy`、`strcat`、`strcmp`、`strstr`、`strncpy`、`strncat`、`strncmp`、`strtok`、`memcpy`、`memmove`和`memset`等函数的使用方法及模拟实现。文章详细讲解了每个函数的功能、参数、返回值,并提供了具体的代码示例,帮助读者更好地理解和掌握这些函数的应用。
76 0
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
703 1
|
8天前
|
JVM: 内存、类与垃圾
分代收集算法将内存分为新生代和老年代,分别使用不同的垃圾回收算法。新生代对象使用复制算法,老年代对象使用标记-清除或标记-整理算法。
18 3
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
3月前
|
JVM内存参数
-Xmx[]:堆空间最大内存 -Xms[]:堆空间最小内存,一般设置成跟堆空间最大内存一样的 -Xmn[]:新生代的最大内存 -xx[use 垃圾回收器名称]:指定垃圾回收器 -xss:设置单个线程栈大小 一般设堆空间为最大可用物理地址的百分之80
|
3月前
|
JVM运行时数据区(内存结构)
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一 (3)程序计数器:保存指令执行的地址,方便线程切回后能继续执行代码
40 3
Elasticsearch集群JVM调优堆外内存
Elasticsearch集群JVM调优堆外内存
75 1
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等