我们在之前的学习中已经明白了操作系统内存的使用方式。
内存分为栈区、堆区、静态区,栈区储存局部变量和函数的形式参数等,静态区存储全局变量和静态变量等。而堆区则被用于动态内存分配。
void* malloc ( size_t size ) ;
这个函数向内存申请了一块连续可用的内存。
void free ( void* memblock ) ;
free函数用于做动态内存的释放与回收。
1)如果开辟空间成功,则返回指向这块空间的指针。如果失败,就返回一个空指针。
2)返回的指针类型为void*类型,当使用时需要强制类型转换。
3)参数size为开辟空间的大小,单位为字节。
4)在使用动态内存时要养成良好习惯:
①判断空间是否成功开辟(判断接收返回值的指针是否为空);
②动态申请的空间不再使用时,通过free函数返还给操作系统;
③返还内存空间后需要把刚才使用的指针置为空,防止成为野指针;
5)如果free的参数指向的空间必须是动态内存开辟的。
6)当free的参数时NULL指针,则函数什么事情都不做。
#include
#include
#include
int main()
{
//向内存申请10个整型的空间
int* p = (int*)malloc(10*(sizeof(int));
if(p == NULL)
{
//打印错误原因
printf("%s\n",strerror(errno));
}
else
{
//正常使用
int i = 0;
for(i=0;i<10;i++)
{
*(p+1) = i;
}
for(i=0;i<10;i++)
{
printf("%d",*(p+i));
}
}
//将空间释放并将指针置为空
free(p);
p = NULL;
return 0;
}
void* calloc ( size_t num , size_t size ) ;
该函数的功能是为num个大小为size的元素开辟一块空间(即开辟num*size大小的空间),并将空间中的每一个字节都初始化为0 。
#include
#include
#include
int main()
{
//向内存申请10个整型的空间
//int* p = (int*)malloc(10*(sizeof(int));
int* p = (int*)calloc(10,sizeof(int));
if(p == NULL)
{
//打印错误原因
printf("%s\n",strerror(errno));
}
else
{
//正常使用
int i = 0;
//calloc已完成空间内字节的初始化
//for(i=0;i<10;i++)
//{
// *(p+1) = i;
//}
for(i=0;i<10;i++)
{
printf("%d",*(p+i));
}
}
//将空间释放并将指针置为空
free(p);
p = NULL;
return 0;
}
realloc函数可以做到对开辟的内存大小的调整。
void* realloc ( void* memblock , size_t size ) ;
1)realloc传递的是需要调整的内存地址和调整之后的大小,返回的是调整之后内存的起始位置。
2)realloc在调整大小的基础上会将原内存中的数据拷贝到新的空间内。
3)realloc在调整内存空间存在两种情况:
①原空间之后有足够大的空间:原申请空间的地址不变,在其后拓展,返回原申请空间地址;
②原空间之后没有足够大的空间:新建足够大的空间,将原申请空间释放,并将其中的数据复制至新建的空间内,返回新开辟的内存空间地址。
由于这两种情况的原因,需要一个新的变量来接收realloc函数的返回值,当用原指针变量接收时,会出现空指针赋值的情况,不仅新的申请空间申请失败,还会使得原申请空间丢失。
#include
#include
#include
int main()
{
//向内存申请10个整型的空间
int* p = (int*)malloc(20);
if(p == NULL)
{
//打印错误原因
printf("%s\n",strerror(errno));
}
else
{
//正常使用
int i = 0;
for(i=0;i<5;i++)
{
*(p+1) = i;
}
//现在已经通过malloc开辟了20个字节的空间
//现在需要将空间拓展为40个字节
p2 = realloc(p,40);
if(p2 == NULL)
{
printf("%s\n",strerror(erron));
}
else
{
p = p2;
for(i=0;i<10;i++)
{
printf("%d",*(p+i));
}
}
}
//将空间释放并将指针置为空
free(p);
p = NULL;
return 0;
}
int main()
{
int* p = (int*)malloc(INT_MAX);
*p = 20;//p的值为NULL,报错
free(p);
}
void test()
{
int i = 0;
int *p = (int*)malloc(5*sizeof(int));
if(p == NULL)
{
return 0;
}
else
{
int i = 0;
for(i=0;i<10;i++) //越界访问
{
*(p+i) = i;
}
}
free(p);
p = NULL;
return 0;
}
void test()
{
int a = 10;
int* p = &a;
free(p); //释放非堆区内存
p = NULL;
}
void test()
{
int* p = (int*)malloc(100);
p++;
free(p); //p的值变化,p不再指向动态内存的起始位置
}
int main()
{
int* p = (int*)malloc(40);
if(p == NULL)
{
return 0;
}
free(p);
//...
free(p);
//对同一块动态内存的多次释放
return 0;
}
int main()
{
while(1)
{
malloc(1);
}
return 0;
}