您的位置:首页 > 编程语言 > C语言/C++

C语言之动态内存分配与释放

2018-02-12 22:00 731 查看

一,堆内存

1,堆内存特点

堆内存可以存放任意类型的数据,但需要自己申请与释放。

2,堆大小

堆大小,想像中的无穷大,但实际使用中,受限于实际内存的大小和内存是否有连续性。

二,堆内存的申请与释放

1,malloc函数

函数声明:·
void *malloc(size_t Size)


所在文件:
stdlib.h


参数:
size_t Size (Size表示要申请的字节数)


返回值:
void * (成功则返回“指向申请空间的指针”,失败则返回NULL)


函数功能:
申请Size个字节的堆内存并返回内存空间首地址


2,calloc函数

函数声明:
void *calloc(size_t nmemb,size_t size)


所在文件:
stdlib.h


参数:
size_t nmemb  size_t size(申请nmemb个大小为size的内存单元)


返回值:
void * (成功则返回“指向申请空间的指针”,失败则返回NULL)


函数功能:
申请具有若干个具有固定单元大小的堆内存空间,自动清零


3,realloc函数

函数声明:
void *realloc(void *ptr,size_t size)


所在文件:
stdlib.h


参数:
void *ptr ,size_t size (ptr表示原有堆内存空间的指针,size表示扩容后的堆内存空间的大小,扩容后的指针可能会改变,若原堆内存空间“后”没有足够的连续堆内存空间提供扩容)


返回值:
void * (对原堆内空间进行扩容)


功能:
对原堆内空间进行扩容


4,free函数

函数声明:
void free(void *p)


所在文件:
stdlib.h


参数:
void *p(指向堆内申请的合法空间)


返回值:
void


功能:
释放手动申请的堆内合法内存空间


示例:

#include<stdio.h>
#include<stdlib.h>

int main()
{
short *p=malloc(100);//以字节为单位
if(NULL == p)
{
printf("Malloc Error!\n");
return -1;
}
free(p);
int
}


realloc函数只能扩容而不能缩容。

realloc函数扩容之后返回的指针和指针可能不同,可能相同。因为,若在原堆内存空间之后有足够大的并且是连续的空间供扩容使用,则返回的指针与原指针相同;否则,就会另找一块足够大的连续空间开辟“扩容后大小”的 堆内存空间,将原堆内存空间里的值复制到新的内存空间并释放掉原堆内存空间。最后,返回新开辟的堆内存空间的首地址。

三,应用(动态数组)

#include<stdio.h>
#include<stdlib.h>

int main()
{
int Size,newSize;
printf("Please input Array Size:\n");
scanf("%d",&Size);
int *pa=(int *)malloc(Size,sizeof(int));
if(NULL == pa)
return -1;
for(int I=0;i<Size;++i)
{
pa[i]=i;
}

printf("Please input Array New Size:\n");
scanf("%d",&newSize);
pa=(int *)realloc(newSize,sizeof(int));
if(NULL == pa)
return -1;
for(int i=Size;i<newSize;++i)
{
pa[i]=1000;
}

printf("Output Array!\n");
for(int I=0;i<newSize;++i)
{
printf("%d\n",pa[i]);
}
return 0;
}


四,错误案例

以下三个模型,是针对堆内存的使用特点而设计的:

自申请、自释放

返回判空

配对使用

1,申请返回判空

释放以后未置为NULL或继续使用

char *p=(char *)malloc(100);
if(NULL == p)
{
return -1;
}
strcpy(p,"hello");
free(p);
//p指向的空间被释放,但p内保存的地址仍然存在,并且变成非法空间
p=NULL;
//将p置为空(NULL),防止p所指向的空间被使用
//若仅仅释放而不置空,则可能会出现下来的错误
if(NULL != p)
{
strcpy(p,"hello");//会因为使用了非法内存而出错
}


2,服务器模型

未释放原有空间,而重新申请新空间,造成原有空间内存泄漏

while(1)
{
char *
4000
p=(char *)malloc(1000);//在堆上申请空间
if(NULL == p)
{
printf("Malloc Error!\n");
return -1;
}
printf("XXXXXX\n");
printf("oooooo\n");
p=(char *)malloc(1000);
//之前在堆上申请的空间尚未释放而又申请了一段新的空间,造成内存泄漏
free(p);
}


3,谁申请谁释放模型(并非绝对)

如果没有协同的原则,则可能会造成重复释放

void func(char *p)
{
strcpy(p,"America");
printf("%s\n",p);
free(p);//此处违反了谁申请谁释放的原则
}
int main()
{
char *p=(char *)malloc(100);
if(NULL == p)
{
printf("Malloc Error!\n");
return -1;
}
func(p);
free(p);//main中申请的堆空间,在main函数中释放
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息