目录
前言
一:malloc,calloc,realloc,free四大函数
1.malloc
2.free
3.calloc
4.realloc
二:常见错误分析
1.malloc返回值不检查直接使用
2.对动态开辟空间的越界访问
3.对非动态开辟空间free
4.使用free释放动态开辟内存的一部分
5.对同一块动态内存多次释放
6.对动态内存空间未释放--内存泄漏
三:柔性数组
1.定义
2.特点
3.使用
4.内存分配规则
5.非柔性数组方法
6.柔性数组的优势
四:c/c++中程序内存区域划分
接下来的日子会顺顺利利,万事胜意,生活明朗-----------林辞忧
前言
对于c语言的动态内存管理是在原先定义数组时,数组的大小被指定,无法修改,可能造成空间的浪费或者空间不够造成越界访问,所以在此基础上提出用malloc,calloc,realloc,free四大函数来维护,自己开辟想要的空间大小,并自己释放,而柔性数组也是用来动态开辟空间的,接下来一一介绍
一:malloc,calloc,realloc,free四大函数
1.malloc
1.这个函数是用来向内存申请 一块连续可用的空间,并返回指向这块空间的指针
2.如果开辟成功,返回一个指向开辟好空间的指针
3.如果开辟失败,则返回一个NULL,因此malloc必须做返回值检查
4.返回类型为void*,需要自己根据需要调整
5.如果size为0,这种行为是未定义的,取决于编译器
#include <stdio.h>
int main()
{
int *p=(int*)malloc(5*sizeof(int));
if(p==NUL)
{
perror("malloc fail");
return ;
}
int i=0;
for(i=0;i<5;i++)
{
*(p+i)=i+1;
}
for(i=0;i<5;i++)
{
printf("%d ",p[i]);
}
free(p);//动态开辟的空间必须释放
p=NULL;
}
2.free
用来对动态开辟的内存空间释放和回收的
1.如果参数 ptr 指向的空间不是动态开辟的,那free函数的⾏为是未定义的。
2.如果参数 ptr 是NULL指针,则函数什么事都不做
3.必须是动态开辟空间的起始地址,所以对于动态内存申请过程中有p++这种如果在释放时只释放部分空间,这种行为是不允许的,释放应该是整体全部释放
4.free释放完空间后,需要手动将指针置为NULL
3.calloc
1.calloc也是用来动态内存分配的
2.函数的功能是为 num 个⼤⼩为 size 的元素开辟⼀块空间,并且把空间的每个字节初始化为0。
3.与malloc函数的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0.
4.如果我们要对动态申请的内存空间要求初始化时,就是用calloc函数
4.realloc
1.有时对于动态开辟的空间 太小或者太大,我们需要做出调整,这时就用realloc函数来调整动态开辟内存大小
2.ptr是要调整的内存地址,size是调整之后新大小,返回值是调整之后的内存起始地址
3.realloc在调整内存空间的两种情况
4.当ptr为NULL时,realloc和malloc作用一样
原地扩容
异地扩容
使用
二:常见错误分析
1.malloc返回值不检查直接使用
#include <stdio.h>
int main()
{
int *p=(int*)malloc(5*sizeof(int));
*p=20;//如果指针p为空,则直接对空指针解引用错误
free(p);
}
正确的应该检查malloc的返回值,不为空再进行相应操作
2.对动态开辟空间的越界访问
int main()
{
int i = 0;
int *p = (int *)malloc(10*sizeof(int));
if(NULL == p)
{
perror("malloc fail");
return ;
}
for(i=0; i<=10; i++)
{
*(p+i) = i;//当i是10的时候越界访问
}
free(p);
return 0;
}
3.对非动态开辟空间free
int main()
{
int a=10;
int*p=&a;
free(p);//对非动态开辟空间进行free直接出错
return 0;
}
4.使用free释放动态开辟内存的一部分
int main()
{
int *p=(int*)malloc(5*sizeof(int));
if(p==NUL)
{
perror("malloc fail");
return ;
}
p++;
free(p);//这样只会释放一部分
}
5.对同一块动态内存多次释放
void test()
{
int *p = (int *)malloc(100);
free(p);
free(p);//重复释放
}
6.对动态内存空间未释放--内存泄漏
int main()
{
int *p = (int *)malloc(100);
if(NULL != p)
{
*p = 20;
}
//未释放动态开辟空间,内存泄漏
return 0;
}
三:柔性数组
1.定义
结构体中最后一个成员是数组,但数组没有指定大小
struct S
{
int n;
int a[];//或者int a[0];
};
2.特点
1.结构中的柔性数组成员前⾯必须⾄少⼀个其他成员
2.sizeof 返回的这种结构⼤⼩不包括柔性数组的内存
3.包含柔性数组成员的结构⽤malloc ()函数进⾏内存的动态分配,并且分配的内存应该⼤于结构的⼤ ⼩,以适应柔性数组的预期⼤⼩
3.使用
4.内存分配规则
就如上面用malloc来开辟空间时,内存上为
5.非柔性数组方法
#include <stdio.h>
#include <stdlib.h>
typedef struct st_type
{
int i;
int *p_a;
}type_a;
int main()
{
type_a *p = (type_a *)malloc(sizeof(type_a));
p->i = 100;
p->p_a = (int *)malloc(p->i*sizeof(int));
//业务处理
for(i=0; i<100; i++)
{
p->p_a[i] = i;
}
//释放空间
free(p->p_a);
p->p_a = NULL;
free(p);
p=NULL;
return 0;
}
6.柔性数组的优势
1.方便内存释放
2.有利于提高访问速度