C语言多线程内存管理模块DOC.docx
- 文档编号:9042520
- 上传时间:2023-02-02
- 格式:DOCX
- 页数:18
- 大小:71.90KB
C语言多线程内存管理模块DOC.docx
《C语言多线程内存管理模块DOC.docx》由会员分享,可在线阅读,更多相关《C语言多线程内存管理模块DOC.docx(18页珍藏版)》请在冰豆网上搜索。
C语言多线程内存管理模块DOC
C语言多线程内存管理模块
摘要:
一个多线程动态内存管理模块,可以有效地检测C语言中内存泄漏和内存越界等错误。
1原理
●分配
通过重新改写内存分配函数,把调用时的信息保存在一个节点中,节点中包括此内存分配的首地址,大小以及分配所在的源文件、函数、行号,并用一个HASH表来保存所有节点。
●越界检测
为了检测写越界的错误,在用户申请的内存前后各增加了一定大小的内存作为监测区域,并初始化成预定值(0xdeadbeef)。
如果发生越界写操作时,预定值就会发生改变,即可检测到越界操作错误。
●释放
重新改写内存释放函数free,释放时节点从HASH表中删除并进行越界检测。
●查看
手动调用show_memory()或show_memory_summary()查看内存使用情况并进行越界检测。
以下涉及内存分配和内存释放的函数被重新改写:
1.malloc
2.calloc
3.realloc
4.strdup
5.strndup
6.asprintf
7.vasprintf
HASH表如下图所示:
节点结构如下:
staticstructmm_region
{
structmm_region*next;
charfile[40];/*分配所在的文件*/
charfunc[40];/*分配所在的函数*/
unsignedintlineno;/*分配所在的行*/
size_tlen;/*内存分配的大小*/
unsignedintfence;/*内存起始边界,用于头越界检测*/
unsignedchardata[0];/*用户内存分配首地址,malloc等函数返回以此为首地址的len长度的一块内存*/
}*regions[SOME_PRIME];
内存中一条节点的结构:
2测试
步骤:
1.引入头文件:
在需要检测的C/C++文件中引入”mm.h”头文件;
2.查看内存使用情况:
调用show_memory()函数查看本文件中内存泄漏详细情况,或调用show_memory_summary()函数查看本文件中内存泄漏统计情况。
2.1内存泄漏
2.1.1测试代码
#include
/*加入头文件mm.h*/
#include"mm.h"
intmain(intargc,char*argv[])
{
char*mp=NULL;
char*cp=NULL;
mp=(char*)malloc(6);
cp=(char*)calloc(1,10);
/*查看内存泄漏*/
show_memory();
show_memory_summary();
return0;
}
2.1.2测试结果
2.2内存越界
2.2.1测试代码
#include
/*加入头文件mm.h*/
#include"mm.h"
intmain(intargc,char*argv[])
{
char*mp=NULL;
mp=(char*)malloc(6);
/*越界操作*/
memset(mp,0,10);
/*释放或查看内存时检测*/
free(mp);
return0;
}
2.2.2测试结果
2.3释放错误
此类错误包括:
1.释放空指针
2.释放野指针
3.重复释放
4.内存释放的起始地址与内存分配的起始地址不一致
2.3.1测试代码
#include
/*加入头文件mm.h*/
#include"mm.h"
intmain(intargc,char*argv[])
{
char*mp=NULL;
mp=(char*)malloc(6);
free(mp);
/*重复释放*/
free(mp);
return0;
}
2.3.2测试结果
3源码
两个文件:
”mm.h”和“mm.c”
3.1mm.h
/*
*mm.h
*
*memoryusagedebugging(fromAsterisk)
*/
#ifndef__MM_H__
#define__MM_H__
#ifdef__cplusplus
extern"C"{
#endif
/*Undefineanymacros*/
#undefmalloc
#undefcalloc
#undeffree
#undefrealloc
#undefstrdup
#undefstrndup
#undefasprintf
#undefvasprintf
void*__mm_calloc(size_tnmemb,size_tsize,constchar*file,intlineno,constchar*func);
void*__mm_malloc(size_tsize,constchar*file,intlineno,constchar*func);
void__mm_free(void*ptr,constchar*file,intlineno,constchar*func);
void*__mm_realloc(void*ptr,size_tsize,constchar*file,intlineno,constchar*func);
char*__mm_strdup(constchar*s,constchar*file,intlineno,constchar*func);
char*__mm_strndup(constchar*s,size_tn,constchar*file,intlineno,constchar*func);
int__mm_asprintf(constchar*file,intlineno,constchar*func,char**strp,constchar*format,...);
int__mm_vasprintf(char**strp,constchar*format,va_listap,constchar*file,intlineno,constchar*func);
/*Provideourowndefinitions*/
#definecalloc(a,b)\
__mm_calloc(a,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
#definemalloc(a)\
__mm_malloc(a,__FILE__,__LINE__,__PRETTY_FUNCTION__)
#definefree(a)\
__mm_free(a,__FILE__,__LINE__,__PRETTY_FUNCTION__)
#definerealloc(a,b)\
__mm_realloc(a,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
#definestrdup(a)\
__mm_strdup(a,__FILE__,__LINE__,__PRETTY_FUNCTION__)
#definestrndup(a,b)\
__mm_strndup(a,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
#defineasprintf(a,b,c...)\
__mm_asprintf(__FILE__,__LINE__,__PRETTY_FUNCTION__,a,b,c)
#definevasprintf(a,b,c)\
__mm_vasprintf(a,b,c,__FILE__,__LINE__,__PRETTY_FUNCTION__)
intshow_memory(void);
intshow_memory_summary(void);
#ifdef__cplusplus
}
#endif
#endif/*__MM_H__*/
3.2mm.c
/*
*mm.c
*
*MemoryManagement(fromAsterisk)
*
*/
#include
#include
#include
#include
#include
#include"mm.h"
/*本文中不使用自定义malloc,calloc,free等函数*/
#undefmalloc
#undefcalloc
#undefrealloc
#undefstrdup
#undefstrndup
#undeffree
#undefvasprintf
#undefasprintf
#defineSOME_PRIME563
#defineFENCE_MAGIC0xdeadbeef
staticstructmm_region
{
structmm_region*next;
charfile[40];/*分配所在的文件*/
charfunc[40];/*分配所在的函数*/
unsignedintlineno;/*分配所在的行*/
size_tlen;/*内存分配的大小*/
unsignedintfence;/*内存起始边界,用于头越界检测*/
unsignedchardata[0];/*用户内存分配首地址,malloc等函数返回以此为首地址的len长度的一块内存*/
}*regions[SOME_PRIME];
#defineHASH(a)\
(((unsignedlong)(a))%SOME_PRIME)
staticpthread_mutex_tmmlock=PTHREAD_MUTEX_INITIALIZER;
#definemm_log(...)\
do{\
fprintf(stderr,__VA_ARGS__);\
}while(0)
staticinlinevoid*__mm_alloc_region(size_tsize,constchar*file,intlineno,constchar*func)
{
structmm_region*reg;
void*ptr=NULL;
unsignedint*fence;
inthash;
if(!
(reg=(structmm_region*)malloc(size+sizeof(*reg)+sizeof(*fence))))/*使用系统malloc*/
{
mm_log("MemoryAllocationFailure-'%d'bytesinfunction%s"
"atline%dof%s\n",(int)size,func,lineno,file);
}
strncpy(reg->file,file,sizeof(reg->file));
strncpy(reg->func,func,sizeof(reg->func));
reg->lineno=lineno;
reg->len=size;
ptr=reg->data;
hash=HASH(ptr);
/*内存起始标志*/
reg->fence=FENCE_MAGIC;
/*内存结束标志*/
fence=(unsignedint*)(ptr+reg->len);
*fence=FENCE_MAGIC;
pthread_mutex_lock(&mmlock);
reg->next=regions[hash];/*一个hash可能对应多个值*/
regions[hash]=reg;
pthread_mutex_unlock(&mmlock);
returnptr;
}
staticinlinesize_t__mm_sizeof_region(void*ptr)
{
inthash=HASH(ptr);
structmm_region*reg;
size_tlen=0;
pthread_mutex_lock(&mmlock);
for(reg=regions[hash];reg;reg=reg->next)
{
if(reg->data==ptr)
{
len=reg->len;
break;
}
}
pthread_mutex_unlock(&mmlock);
returnlen;
}
staticvoid__mm_free_region(void*ptr,constchar*file,intlineno,constchar*func)
{
inthash=HASH(ptr);
structmm_region*reg,*prev=NULL;
unsignedint*fence;
pthread_mutex_lock(&mmlock);
for(reg=regions[hash];reg;reg=reg->next)
{
if(reg->data==ptr)
{
if(prev)
prev->next=reg->next;
else
regions[hash]=reg->next;
break;
}
prev=reg;
}
pthread_mutex_unlock(&mmlock);
if(reg)
{
/*头越界检测*/
if(reg->fence!
=FENCE_MAGIC)
{
mm_log("WARNING:
Headfenceviolationat%p,in%sof%s,"
"line%d\n",reg->data,reg->func,reg->file,reg->lineno);
}
/*尾越界检测*/
fence=(unsignedint*)(reg->data+reg->len);
if(*fence!
=FENCE_MAGIC)
{
mm_log("WARNING:
Tailfenceviolationat%p,in%sof%s,"
"line%d\n",reg->data,reg->func,reg->file,reg->lineno);
}
free(reg);
}else
{
mm_log("WARNING:
Freeingunusedmemoryat%p,in%sof%s,line%d\n",
ptr,func,file,lineno);
}
}
void*__mm_calloc(size_tnmemb,size_tsize,constchar*file,intlineno,constchar*func)
{
void*ptr;
if((ptr=__mm_alloc_region(size*nmemb,file,lineno,func)))
memset(ptr,0,size*nmemb);
returnptr;
}
void*__mm_malloc(size_tsize,constchar*file,intlineno,constchar*func)
{
return__mm_alloc_region(size,file,lineno,func);
}
void__mm_free(void*ptr,constchar*file,intlineno,constchar*func)
{
__mm_free_region(ptr,file,lineno,func);
}
void*__mm_realloc(void*ptr,size_tsize,constchar*file,intlineno,constchar*func)
{
void*tmp;
size_tlen=0;
if(ptr&&!
(len=__mm_sizeof_region(ptr))){
mm_log("WARNING:
Reallocofunallocedmemoryat%p,in%sof%s,"
"line%d\n",ptr,func,file,lineno);
returnNULL;
}
if(!
(tmp=__mm_alloc_region(size,file,lineno,func)))
returnNULL;
if(len>size)
len=size;
if(ptr){
memcpy(tmp,ptr,len);
__mm_free_region(ptr,file,lineno,func);
}
returntmp;
}
char*__mm_strdup(constchar*s,constchar*file,intlineno,constchar*func)
{
size_tlen;
void*ptr;
if(!
s)
returnNULL;
len=strlen(s)+1;
if((ptr=__mm_alloc_region(len,file,lineno,func)))
strcpy((char*)ptr,s);
return(char*)ptr;
}
char*__mm_strndup(constchar*s,size_tn,constchar*file,intlineno,constchar*func)
{
size_tlen;
void*ptr;
if(!
s)
returnNULL;
len=strlen(s)+1;
if(len>n)
len=n;
if((ptr=__mm_alloc_region(len,file,lineno,func)))
strcpy((char*)ptr,s);
return(char*)ptr;
}
int__mm_asprintf(constchar*file,intlineno,constchar*func,char**strp,constchar*fmt,...)
{
intsize;
va_listap,ap2;
chars;
*strp=NULL;
va_start(ap,fmt);
va_copy(ap2,ap);
size=vsnprintf(&s,1,fmt,ap2);
va_end(ap2);
if(!
(*strp=(char*)__mm_alloc_region(size+1,file,lineno,func)))
{
va_end(ap);
return-1;
}
vsnprintf(*strp,size+1,fmt,ap);
va_end(ap);
returnsize;
}
int__mm_vasprintf(char**strp,constchar*fmt,va_listap,constchar*file,intlineno,constchar*func)
{
intsize;
va_listap2;
chars;
*strp=NULL;
va_copy(ap2,ap);
size=vsnprintf(&s,1,fmt,ap2);
va_end(ap2);
if(!
(*strp=(char*)__mm_alloc_region(size+1,file,lineno,func)))
{
va_end(ap);
return-1;
}
vsnprintf(*strp,size+1,fmt,ap);
returnsize;
}
intshow_memory(void)
{
char*fn=NULL;
structmm_region*reg;
unsignedintx;
unsignedintlen=0;
unsignedintcount=0;
unsignedint*fence;
mm_log("\nLEAKDETAIL:
\n");
pthread_mutex_lock(&mmlock);
for(x=0;x { for(reg=regions[x];reg;reg=reg->next) { if(! fn||! strcasecmp(fn,reg->file)||! strcasecmp(fn,"anomolies")) { /*头越界检测*/ if(reg->fence! =FENCE_MAGIC) { mm_log("WARNING: Headfenceviolationat%p," "in%sof%s,line%d\n",reg->data, reg->func,reg->file,reg->lineno); } /*尾越界检测*/ fence=(unsignedint*)(reg->data+reg->len); if(
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 多线程 内存 管理 模块 DOC