C语言重点难点精讲C语言内存管理
Posted 我擦了DJ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言重点难点精讲C语言内存管理相关的知识,希望对你有一定的参考价值。
C语言内存管理其实是一个很糟糕的话题,很烦这个,但是没有办法,考试就爱考这些东西
一:相关动态内存函数
(1)malloc和free
int main()
{
//malloc返回值为void*,所以需要进行强转
int* p = (int*)malloc(sizeof(int) * 10);
//malloc有可能申请失败
if (p == NULL) {
printf("%s\\n", strerror(errno));
}
else {
for (int i = 0; i < 10; i++) {
p[i] = i;
}
for (int j = 0; j < 10; j++) {
printf("%d ", *(p + j));
}
}
return 0;
}
free用于释放mallco开辟的空间,malloc和free要成对使用,开辟的空间如果不使用了,一定要将其free掉,如果不free掉,堆区空间会越挤越大的(除非程序直接结束)。同时当那个指针所指空间free掉之后,由于指针其实还是已经保存了那片空间的地址,这个行为是相当危险的,因为找到指针就有可能会改变它,所以为了彻底断绝他们的联系,在free掉之后,要将指针置为NULL
free(p);
p = NULL;
(2)calloc
calloc函数和malloc函数的作用相同,都是用来动态开辟的。calloc与malloc所不同的是地方是两者参数格式不一样,并且calloc在开辟的同时会将此空间初始化为0, 而malloc则为随机值
- malloc情况
calloc语法格式为
int* p=(int*) calloc(10,sizeof(int));
(3)realloc
在申请好空间后,如果发现申请的空间不合适,过大或者过小,就可以使用realloc来进行调整
比如下面的例子中申请了20个字节后发现空间不够,然后重新调整
int main()
{
int* p = (int*)malloc(20);//20字节数据
if (p == NULL) {
printf("%s\\n", strerror(errno));
}
else {
for (int i = 0; i < 5; i++) {
p[i] = i;
}
}
int*p1 = realloc(p, 40);//将空间调整为40字节,并返回调整后的地址
for (int j = 0; j < 10; j++) {
printf("%d ", *(p + j));
}
free(p1);
p = NULL;
return 0;
}
需要注意:realloc申请空间有两种方式
在堆区重新调整空间必然会遇到两种情况,第一种原有的空间后面有足够大的空间,那么申请时相当于就在原有空间后面补上缺的部分,这样其返回的仍然是原来空间的地址;第二种原有的空间后面不够大,realloc会重新找一片能完整存放的区域,然后把之前的内容照搬赋值过来,并释放先前空间
二:进程地址空间
C/C++程序的地址空间排布如下
用一个例子说明如下
#include <stdio.h>
#include <stdlib.h>
int gobal_val=100;//全局变量已经初始化
int gobal_unval;//全局变量未初始化
int main(int argc,char* argv[],char* env[])
{
printf("main函数处于代码段,地址为:%p,十进制为:%d\\n",main,main);
printf("\\n");
printf("全局变量gobal_val,地址为:%p,十进制为:%d\\n",&gobal_val,&gobal_val);
printf("\\n");
printf("全局变量未初始化gobal_unval,地址为:%p,十进制为:%d\\n",&gobal_unval,&gobal_unval);
printf("\\n");
char* mem=(char*)malloc(10);
printf("mem开辟的堆空间,mem是堆的起始地址,是%p,十进制为:%d\\n",mem,mem);
printf("\\n");
printf("mem是指针变量,指针变量在栈上开采,其地址为%p,十进制为:%d\\n",&mem,&mem);
printf("\\n");
printf("命令行参数起始地址:%p,十进制为:%d\\n",argv[0],argv[0]);
printf("\\n");
printf("命令行参数结束地址:%p,十进制为:%d\\n",argv[argc-1],argv[argc-1]);
printf("\\n");
printf("第一个环境变量的地址:%p,十进制为:%d\\n",env[0],env[0]);
printf("\\n");
}
三:常见内存错误
1:对空指针进行解引用
2:越界访问
动态内存指的是动态指的是在需求改变时我们可以随时更改内存,但是它毕竟每次申请出来的也是一个确定的空间,所以你的指针不能跑到空间外面去
3:对非动态内存进行free
4:使用free释放一块动态开辟内存的一部分
free释放的是开辟的空间的首位置,使用时指针不能变化,不然就非法释放别的内存了
5:对同一块动态内存多次释放
6:内促泄漏
如果开辟的内存忘记释放(当然是工程量大的情况),极易造成内存泄漏,而排查内存泄漏是一项很麻烦的事
以上是关于C语言重点难点精讲C语言内存管理的主要内容,如果未能解决你的问题,请参考以下文章