C语言 动态内存分配的详解及实例
1.动态内存分配的意义
(1)C语言中的一切操作都是基于内存的。
(2)变量和数组都是内存的别名。
①内存分配由编译器在编译期间决定
②定义数组的时候必须指定数组长度
③数组长度是在编译期就必须确定的
(3)但是程序运行的过程中,可能需要使用一些额外的内存空间
2.malloc和free函数
(1)malloc和free用于执行动态内存分配的释放
(2)malloc所分配的是一块连续的内存
(3)malloc以字节为单位,并且返回值不带任何的类型信息:void*malloc(size_tsize);
(4)free用于将动态内存归还系统:voidfree(void*pointer);
(5)_msize(void*pointer)可以获取malloc出来的内存空间大小
3.使用malloc和free需要注意的地方
(1)malloc和free是库函数,而不是系统调用
(2)malloc实际分配的内存可能有会比请求的多,但不能依赖于不同平台下的malloc行为。
(3)当请求的动态内存无法满足时,malloc返回NULL
(4)当free的参数为NULL时,函数直接返回
malloc(0)返回什么?
#include<stdio.h> #include<malloc.h> intmain() { inti=10; int*p=NULL; for(i=0;i<100;i++) { //注意,malloc(0)会返回一个有效的内存地址,大小为1 //但我们不能依赖编译器的这种行为来使用这个字节的空间! p=(int*)malloc(i); printf("%d",_msize(p));//返回malloc出来的内存空间大小 free(p); } return0; }
内存泄漏检测模块
mleak.h
#ifndef_MLEAK_H_ #define_MLEAK_H_ #include<stdio.h> #include<malloc.h> #defineMALLOC(n)mallocEx(n,__FILE__,__LINE__) #defineFREE(p)freeEx(p) void*mallocEx(size_tn,constchar*file,constline); voidfreeEx(void*p); voidPRINT_LEAK_INFO(); #endif
mleak.c
复制代码
#include"mleak.h" #defineSIZE256 //动态内存申请参数结构体 typedefstruct { void*pointer;//申请到的内存地址 intsize;//内存块大小 constchar*file;//文件名 intline;//文件行号 }MItem; staticMItemg_record[SIZE];//记录每个动态内存申请的操作 void*mallocEx(size_tn,constchar*file,constline) { inti=0; void*ret=malloc(n);//动态内存申请 if(ret!=NULL) { //申请成功,则记录下来 //遍历全局数组,记录此次操作 for(i=0;i<SIZE;i++) { //查找位置 if(g_record[i].pointer==NULL) { g_record[i].pointer=ret; g_record[i].size=n; g_record[i].file=file; g_record[i].line=line; break; } } } returnret; } voidfreeEx(void*p) { if(p!=NULL) { inti=0; //遍历全局数组,释放内存空间,并清除操作记录 for(i=0;i<SIZE;i++) { if(g_record[i].pointer==p) { g_record[i].pointer=NULL; g_record[i].size=0; g_record[i].file=NULL; g_record[i].line=0; free(p); break; } } } } voidPRINT_LEAK_INFO() { inti=0; printf("PotenitalMemoryLeakInfo:\n"); //遍历全局数组,打印未释放的空间的申请记录 for(i=0;i<SIZE;i++) { //查找位置 if(g_record[i].pointer!=NULL) { printf("Address:%p,size:%d,Location:%s:%d\n", g_record[i].pointer, g_record[i].size, g_record[i].file, g_record[i].line); } } }
testc.
#include<stdio.h> #include"mleak.h" voidf() { //没释放,会造成内存泄漏! MALLOC(100); } intmain() { int*p=(int*)MALLOC(3*sizeof(int)); f(); p[0]=1; p[1]=2; p[2]=3; FREE(p); PRINT_LEAK_INFO(); return0; } /* 输出结果: E:\Study>gcctest.cmleak.c E:\Study>a.exe PotenitalMemoryLeakInfo: Address:00602ED8,size:100,Location:38-1.c:7 */
4.calloc和realloc函数
(1)malloc的同胞兄弟:
void*calloc(size_tnum,size_tsize);
void*realloc(void*pointer,size_tnew_size);
(2)calloc参数表示要返回num个某种类型(如sizeof(int))大小的内存空间。calloc能以类型大小为单位申请内存并初始化为0.
(3)realloc用于修改一个原先己经分配的内存块大小。当第一个参数pointer为NUL时,等价于malloc。
calloc和realloc的使用
#include<stdio.h> #include<malloc.h> #defineSIZE5 intmain() { inti=0; int*pI=(int*)malloc(SIZE*sizeof(int));//malloc内存没有初始化 short*pS=(short*)calloc(SIZE,sizeof(short));//内存初始化为0 for(i=0;i<SIZE;i++) { printf("pI[%d]=%d,pS[%d]=%d\n",i,pI[i],i,pS[i]); } printf("Before:pI=%p\n",pI);//重置内存大小之前的pI指针 pI=(int*)realloc(pI,2*SIZE*sizeof(int));//内存未初始化的 printf("After:pI=%p\n",pI); for(i=0;i<10;i++) { printf("pI[%d]=%d\n",i,pI[i]); } free(pI); free(pS); return0; }
通过此文希望大家对C语言的动态内存分配了解掌握,谢谢大家对本站的支持!