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语言的动态内存分配了解掌握,谢谢大家对本站的支持!