C语言提供了一个动态内存开辟的函数:
void malloc (size_t size);*
这个函数向申请一块连续可用的空间,并返回指向这块空间的指针。
C语言还提供了另外一个函数free,专门是用来做动态内存的释放和回收的,函数原型如下:
void free(void ptr);
free函数用来释放动态开辟的内存。
malloc和free都声明在stdlib.h头文件中。
C语言还提供了一个函数叫calloc,calloc函数也用来动态内存开辟。原型如下:
void calloc(size_t num,size_t size);*
函数原型如下:
void realloc(void ptr,size_t size);**
情况1: 原有空间之后有足够大的空间
情况2: 原有空间之后没有足够大的空间
#include<stdio.h>
int main()
{
int *p = (int*)malloc(100000000000);//开辟内存过大,可能会开辟失败,返回空指针
int i = 0;
for(i = 0;i<10;i++)
{
*(p+i) = i;
}
}
解决方法:在申请空间后对p进行判断。
if(p == NULL) return 1;
#include<stdio.h>
int main()
{
int *p = (int*)malloc(10*sizeof(int));//申请10个int空间大小
if(p==NULL)
return 1;
int i=0;
// 越界访问
for(i=0;i<40;i++)
{
*(p+i)=i;
}
}
int main()
{
int arr[10]={0}//存于栈区
int *p=arr;
free(p);//使用free释放了数组申请的空间
p=NULL;
return 0;
}
int main()
{
int* p=(int*)malloc(10*sizeof(int));
if(p==NUL)
return 1;
int i=0;
for(i=0;i<5;i++)
{
*p++ = i;
}
free(p);
p=NULL;
return 0;
}
解读:p指向开辟内存的首地址,而在循环赋值中,p只对其中5个int大小进行了赋值,而后就对该空间释放。除此之外p受++运算符不断向后移动,使得p的初始位置改变,这很容易导致内存泄漏。
int main()
{
int* p=(int*)malloc(100);
//使用
//释放
free(p);
p=NULL;
//释放
free(p);
return 0;
}
解决方法:在该指向这块空间的指针的生命周期结束前使用free函数释放。
void GetMemory(char* p)
{
p = (char*)malloc(100);
}
void Test(void)
{
char* str=NULL;
GetMemory(str);
strcpy(str,"hello,liren");
printf(str);
}
请问运行Test函数会有什么样的结果?
答案:程序奔溃!
解读:str传给GetMemory函数的时候是值传递(因为并不是使用str所指地址的值而是改变str本身的值),所以GetMemory函数的形参p是str的一份临时拷贝。在GetMemory函数内部动态申请空间的地址,存放在p中,不会影响外边str,所以当GetMemory函数返回之后,str仍然是NULL,所以strcpy会失败。(当GetMemory函数返回之后,形参p销毁,使得动态开辟的100个字节存在内存泄露)
char* getmemory(void)
{
char p[]="hello,liren";
return p;
}
void test(void)
{
char* str=NULL;
str=getmemory();
printf(str);
}
int main()
{
test();
return 0;
}
这种题称为返回栈空间地址的问题
答案:一堆乱码!
解答:getmemory函数内部创建数组是在栈区上创建的,出了函数,p数组的空间就还给了操作系统,返回的地址是没有实际的意义的,如果通过返回的地址,去访问内存就是非法访问内存的。
void getmemory(char** p,int num)
{
*p = (char*)malloc(num);
}
void test(void)
{
char* str=NULL;
getmemory(&str,100);
strcpy(str,"liren");
printf(str);
}
int main()
{
test();
return 0;
}
答案:程序奔溃!
解答:应在test函数里面使用free函数释放str,并将其设为空指针。
void test(void)
{
char* str=(char*)malloc(100);
strcpy(str,"liren");
free(str);
if(str!=NULL)
{
strcpy(str,"love tongtong");
printf(str);
}
}
int main()
{
test();
return 0;
}
答案:程序奔溃!
解答:test函数中提前free了一次,造成下面的非法访问内存。(注:使用free后并不会将指针置空,必须要手动置空)
到此为止,应该对动态内存开辟有相当的了解了吧,那接下来我会更新如何运用动态内存开辟制作一个通讯录,持续更新!(还将设计文件操作的知识)