1.提到动态内存开辟就要想到内存分配的堆区,
静态区,堆区,栈区介绍和区别详情(点击这里)
2.动态内存开辟是内申请一定的内存,C语言中与申请内存有关的函数有
malloc,calloc,realloc,free,alloca等函数
(1).malloc
malloc的函数申明:void* malloc(unsigned size);
作用:在内存的动态存储区中分配一块长度为size字节的连续区域,参数size为需要内存空间的长度,返回该区域的首地址. 如果申请失败,则返回NULL指针
malloc分配的内存是位于堆中的,并且没有初始化内存的内容,因此基本上malloc之后,调用函数memset来初始化这部分的内存空间
(2).calloc
calloc的函数申明:void* calloc(size_t numElements, size_t sizeOfElement)
作用:与malloc相似,参数sizeOfElement为申请地址的单位元素长度,numElements为元素个数,即在内存中申请numElements*sizeOfElement字节大小的连续地址空间,相当于在mealloc函数中加了一个memeset。
calloc则将初始化这部分的内存,设置为0.
(3).realloc
realloc的函数申明:void* realloc(void* ptr, unsigned newsize)
作用:给一个已经分配了地址的指针重新分配空间,参数ptr为原有的空间地址,newsize是重新申请的地址长度.
相当于对已经分配了的内存调整大小
(4).free
动态内存的开辟需要我们自己释放,动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。 但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,并立即将指针置位NULL,防止产生野指针。
(5).alloca
alloca是向栈申请内存,因此无需我们自己释放.
3.用法代码示例:
malloc:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <error.h>
int main()
{
int *p = malloc(INT_MAX); //如果申请内存太大,申请失败则返回一个NULL指针
if(p==NULL)
{
printf("%s",strerror(errno)); //如果申请失败,则报错
return 0;
}
free(p);
return 0;
}
int main()
{
int *p = calloc(5,sizeof(int)); //申请5个int型元素所占大小空间
int i = 0;
for(i=0; i<5; i++)
printf("%d ",p[i]); //验证结果全初始化为0
free(p);
return 0;
}
int main()
{
int *p = malloc(20);
int *str = NULL;
if(p == NULL) //检查是否开辟成功
{
printf("%s",strerror(errno));
return 0;
}
str = realloc(p,40);//将原先开辟的20字节增加至40字节
if(str != NULL)
p = str; //如果重新开辟空间失败,则不将p替换成str,
free(p); //否则p就变成空指针,原来的p指向的内容就无法读取
return 0;
}
4.常见错误
(1)
void GetMemory(char*p)
{
p = (char*)malloc(100);
}
void Test(void)
{
char* str=NULL;
GetMemory(str);
strcpy(str,"hello world");
printf(str);
free(str);
}
传入的str只是将str临时拷贝一份给形参p,最后str还是NULL。使用strcpy时就会程序崩溃。
应该将str的地址传入,传值的时候再解引用。
(2)想将函数中栈内存中的值返回
char *GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}
p指针指向的内容在栈中存储,当函数结束时,原先指向的内容已经被清除,
所以现在p指向的内容可能是乱码。
(3)内存泄漏
void GetMemory2(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
没有free(str),会使内存泄漏。
(4)野指针
void Test(void)
{
char *str = (char *) malloc(100);
strcpy(str, "hello");
free(str);
if(str != NULL)
{
strcpy(str, “world”);
printf(str);
}
}
free(str)后,没有将str设为空指针,则str变为野指针。(野指针!=NULL)