前言:
对于数据的存储我们可以静态存储,也可以动态存储,两种方式都有自己特有的好处,这篇文章教我们如和进行动态的数据存储!!!!
欢迎来到小马学习代码博客!!!!
要有最朴素的生活,最遥远的梦想 !!!
目录
一、动态内存管理
1.1为什么要有动态内存管理 :
1.2 动态内存介绍:
1.2.1malloc 和 free:
1.2.2 calloc:
1.2.3 realloc:
1.3常见的动态内存错误:
1.3.1对NULL指针解引用操作:
1.3.2对动态内存的越界:
1.3.3对非动态空间进行释放:
1.3.4 动态内存空间的部分释放:
1.3.5对一块动态内存进行多次释放:
1.3.6动态内存忘记释放(内存泄漏):
总结:
1.1.1 在c语言中我们普通的内存开辟是直接在栈上进行开辟的
int i = 20;//在栈空间上开辟四个字节
int arr[10]={0}; //在栈中连续开辟四十个字节
这样开辟的特点是:
(1) 他所开辟的空间是固定的
(2 ) 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配
但对于空间的需求,我们有的时候并不知道,有可能空间开大了造成了浪费,也有可能空间开小了造成栈溢出,这样我们就需要一个动态的内存管理让我们需要多少内存的时候开辟多少。
void* malloc (size_t size);
这个函数想内存中申请一个连续的空间(是在堆中申请),并返回指向这块空间的指针。
如果开辟成功,则返回一个指向开辟好空间的指针。
同样的C语言提供了另外一个函数free,专门是用来做动态内存的释放和回收的
void * free (void * ptr)
free 是用来释放动态开辟的内存的
#include
#include //malloc 和free 都在stdlib.h的头文件里
int main()
{
int arr[10] ={0}; //这是在栈中申请连续的四十个空间 是静态的
int * arr1;
int *ptr ;
ptr =(int*)malloc (10*sizeof(int)); //申请一个动态内存空间为40字节
if(ptr==NULL) //防止申请空间失败传入了空指针
{
perror("ptr");
}
arr1=ptr;
free(arr1); //结束后要进行一个空间的释放
arr1=NULL; //然后在指向空指针防止出现了野指针
//这就是申请一个动态内存空间的套用过程
return 0;
}
c语言同样的提供了一个函数calloc,也是用来动态内存的分配
void* calloc (size_t num, size_t size);
#include
#include //malloc 和free 都在stdlib.h的头文件里
int main()
{
int arr[10] ={0}; //这是在栈中申请连续的四十个空间 是静态的
int * arr1;
int *ptr ;
ptr =(int*)calloc (10,sizeof(int)); //申请一个动态内存空间为40字节
if(ptr==NULL) //防止申请空间失败传入了空指针
{
perror("ptr");
}
arr1=ptr;
free(arr1); //结束后要进行一个空间的释放
arr1=NULL; //然后在指向空指针防止出现了野指针
//这就是申请一个动态内存空间的套用过程
return 0;
}
realloc 使我们申请的的动态内存空间变得灵活,在申请动态内存空间的时候,有时候我们申请的过大,或者申请的过小的时候,我们可以通过realloc也对我们申请的空间进行一个合理的调整改变
void* realloc (void* ptr, size_t size);
#include
#include //malloc 和free 都在stdlib.h的头文件里
int main()
{
int arr[10] ={0}; //这是在栈中申请连续的四十个空间 是静态的
int * arr1;
int *ptr ;
ptr =(int*)calloc (10,sizeof(int)); //申请一个动态内存空间为40字节
if(ptr==NULL) //防止申请空间失败传入了空指针
{
perror("ptr");
}
arr1=ptr;
arr1 =(int*)realloc (arr1,10000); //改变原有的内存空间
free(arr1);
arr1=NULL;
ptr=NULL;
return 0;
}
#include
#include
int main()
{
int *ptr;
ptr=(int*)malloc(sizeof(int));
*ptr=1; //这里有可能申请失败 ,但我这没有失败,为了以防万一还是需要进行判断一下,正确的申请在上面
free(ptr);
ptr=NULL;
return 0;
}
#include
#include //malloc 和free 都在stdlib.h的头文件里
int main()
{
int *ptr ;
ptr =(int*)malloc(40); //申请一个动态内存空间为40字节
if(ptr==NULL) //防止申请空间失败传入了空指针
{
perror("ptr");
}
for(int i=0;i<=11;i++)
{
*(ptr+i)=i; //申请的是四十个字节,这里产生了越界
}
for(int i=0;i<=11;i++)
{
printf("%d ",*(ptr+i));
}
free(ptr);
ptr=NULL;
return 0;
}
#include
#include
int main()
{
int *p;
*p=10;
free(p); //这里的p并不是动态内存空间仍然进行了释放
return 0;
}
#include
#include
int main()
{
int *p=(int*)malloc(sizeof(int)*2);
if(p==NULL)
{
perror("p");
}
p++;
free(p); //这里的p的地址并不是起始地址,只是进行了部分的释放
p=NULL;
}
#include
#include
int main()
{
int *p=(int*)malloc(sizeof(int)*2);
if(p==NULL)
{
perror("p");
}
free(p);
// ~~~~~~~~~~
free(p); // 已经释放p了有进行了释放
p=NULL;
}
这个真的有可能发生,当我们代码写的比较长的时候,我们有可能忘了我们是否已经释放这块空间,就有可能进行重复的释放,这是不正确的,而解决他的方法是,当我们释放了一块空间后,一定让他指为空指针。
#include
#include
void test(int *p)
{
p=(int*)malloc(sizeof(int)*2);
if(p==NULL)
{
perror("p");
}
}
int main()
{
int *ptr;
test(ptr); //这里就是没有对内存进行释放
}
对于动态内存还是比较重要的,因为堆的空间是比栈的空间的是大的,同时我们要知道,动态的是可以进行修改的,我们需要多少内存就可以开辟多少内存,防止了内存的浪费,但是我们在申请动态内存的时候一定要防止一些不必要的错误不然就会得不偿失。
最后小马码文不易,如果觉得有帮助就多多支持哈!!!^ _ ^