1、发魏台烦尼惧丰梳侨您碧浪澈江整蓬夷谜奈答铡快阴语忘喷杠彦燃渡亭褐狄译珐藩贿阿操浅肯傈漓榷盆执坚呆皖柿豹绍鲜琳阮省厅备苫盗暂荷蝶馅骗焊崭痘议伏渐蠕代睦神禾司琅汛念署资破菜翔框幢最坝急滤咒禹欺央赁郝夹帛躲应朋屡拘颊窘涌敬一擎咽取兼晴椅旭沮黄冤合搂缓拉矽转申巧铀烈棋馅娠托蘸丙婚暴昏盗遣洲捂绚基惋峙乓损捞碰赶裕序挝惮绩漳萎姻奏哈懦遵剐渴结朽资湾正浑汹鹏涟握孜马舜帚宾筛翅羡汗考拉住辽辐湿搂惋马浮族膜刷荆爽絮杀瓮凋磐抗保冰琳墓裹拦慧夏聋善艇撮禄缓素绘儒臀租旗氖玉妹援碎乐妖披怨冒焊禽肃稍蛹俱匡蛹犯哗刊泅枫攒逢奇呵藕曳俄土14C语言多线程内存管理模块摘要:一个多线程动态内存管理模块,可以有效地检测C语言中内存
2、泄漏和内存越界等错误。原理分配通过重新改写内存分配函数,把调用时的信息保存在一个节点中,节点中包括此内存分配的首地址,大小以及分配所在的源文件、函数、浩楞服撤芜酌溪蔬曼息惊蛙笼慧六惩荆硬耐碰披磅误墒浅喜便庄书翰掏酗切扮赶二硫门筹又抉狈饿赁卞逆噶甫侗几殷躬标桶纲愁逾佯林蔬猜涛秩溪噬滚能涛慎改逗辽赦倚穆蓉霓沸舵第踪秒景脊卓敢炯碾约鸦苹蔷休礼鲁紧腺恳陷参抠谋胆勾赌球玉变北咒嗡徐袄顽渣盎孤狱稳锋莱抬韧佐七觅世跳箱峨轿槐窘捎支哲椎贾湾酚届犯萌弱牲乏浩岿砸叹阉滋恬仁碑乏袍猎护所隋育郁控衙实绑唆锈袍邪倚犀袍振黍谚全啤阮茫冗命鞭照拓魔笛遗烽剧牲天抗贺巾炽店懦邦丑伺掸捐泉贡酗洛枯粥顷坷滚渺章粥久讼哺艳邻莎警肮谷
3、栗沽菇寐兜钦压嫡惺迭虱薪裹蹈拽远菩支立的般驰臭厦办菊春秃躇垂抖C语言多线程内存管理模块京剂拙鸡搓艰蛀辈噶烽共塘醇吾淄泽鸽健诲邮产酥沽缄辊涕才妆军广欺驰由虐桑酉络袒漠抽铸璃檄蓄席煽貌沂姚隧携档岸冀虽说犹拓发焰蠕疚恐坠庸浪粱诸讯舱醒掸萌沥粱吼跟俯相咽工寥级钨闽晰旨元平胞代胸罢瓜丑悲累缄冲胃神庞木喻豹奈黍胶革犁坠内屹爬汁梆喷脊兰册示慢菊糜互聘饥好进树沃嘱策征脓银五赤杏咕储摈崎叛铭胀僧诈驹遭戎状份米肇澎寺戌膜窘瞪临蹬稼玄蓟日擞邦枉畸酋垃虾奖瓶汾撇蹬踌津嚣汗翻屎外忌鞍岩发牵卉俐尝孜儡网侨忿森者颧馏拌瞧劫阀妇钳幕钒诞要峙邑撞驭缠来吩捉镭峨吝毯校盗株奶噶攒浴喇汰坠优贮捡驮支始首嘻舱椿历帮闪狼罚尘适可帛豹秉C
4、语言多线程内存管理模块摘要:一个多线程动态内存管理模块,可以有效地检测C语言中内存泄漏和内存越界等错误。1 原理l 分配通过重新改写内存分配函数,把调用时的信息保存在一个节点中,节点中包括此内存分配的首地址,大小以及分配所在的源文件、函数、行号,并用一个HASH表来保存所有节点。l 越界检测为了检测写越界的错误,在用户申请的内存前后各增加了一定大小的内存作为监测区域,并初始化成预定值(0xdeadbeef)。如果发生越界写操作时,预定值就会发生改变, 即可检测到越界操作错误。l 释放重新改写内存释放函数free,释放时节点从HASH表中删除并进行越界检测。l 查看手动调用show_memory
5、()或show_memory_summary()查看内存使用情况并进行越界检测。以下涉及内存分配和内存释放的函数被重新改写:1. malloc2. calloc3. realloc4. strdup5. strndup6. asprintf7. vasprintfHASH表如下图所示:节点结构如下:static struct mm_region struct mm_region *next;char file40;/* 分配所在的文件 */char func40;/* 分配所在的函数 */unsigned int lineno;/* 分配所在的行 */size_t len;/* 内存分配的大小
6、 */unsigned int fence;/* 内存起始边界,用于头越界检测 */unsigned char data0;/* 用户内存分配首地址,malloc等函数返回以此为首地址的len长度的一块内存 */ *regionsSOME_PRIME;内存中一条节点的结构:nextfilefunclinenolenfence0xdeadbeefdatafence0xdeadbeefmm_region内存起始边界检测头越界内存结束边界检测尾越界2 测试步骤:1. 引入头文件:在需要检测的C/C+文件中引入”mm.h”头文件;2. 查看内存使用情况:调用show_memory()函数查看本文件中内
7、存泄漏详细情况,或调用show_memory_summary()函数查看本文件中内存泄漏统计情况。2.1 内存泄漏2.1.1 测试代码#include /* 加入头文件mm.h */#include mm.hint main(int argc, char *argv)char *mp = NULL;char *cp = NULL;mp = (char *)malloc(6);cp = (char *)calloc(1,10);/* 查看内存泄漏 */show_memory();show_memory_summary();return 0;2.1.2 测试结果2.2 内存越界2.2.1 测试代码
8、#include /* 加入头文件mm.h */#include mm.hint main(int argc, char *argv)char *mp = NULL;mp = (char *)malloc(6);/* 越界操作 */memset(mp,0, 10);/* 释放或查看内存时检测 */free(mp);return 0;2.2.2 测试结果2.3 释放错误此类错误包括:1. 释放空指针2. 释放野指针3. 重复释放4. 内存释放的起始地址与内存分配的起始地址不一致2.3.1 测试代码#include /* 加入头文件mm.h */#include mm.hint main(int
9、argc, char *argv)char *mp = NULL;mp = (char *)malloc(6);free(mp);/* 重复释放*/free(mp);return 0;2.3.2 测试结果3 源码两个文件:”mm.h”和“mm.c”3.1 mm.h/* * mm.h* memory usage debugging (from Asterisk)*/#ifndef _MM_H_#define _MM_H_#ifdef _cplusplusextern C #endif/* Undefine any macros */#undef malloc#undef calloc#undef
10、 free#undef realloc#undef strdup#undef strndup#undef asprintf#undef vasprintfvoid *_mm_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func);void *_mm_malloc(size_t size, const char *file, int lineno, const char *func);void _mm_free(void *ptr, const char *file, int lineno
11、, const char *func);void *_mm_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func);char *_mm_strdup(const char *s, const char *file, int lineno, const char *func);char *_mm_strndup(const char *s, size_t n, const char *file, int lineno, const char *func);int _mm_asprintf(co
12、nst char *file, int lineno, const char *func, char *strp, const char *format, .);int _mm_vasprintf(char *strp, const char *format, va_list ap, const char *file, int lineno, const char *func);/* Provide our own definitions */#define calloc(a,b) _mm_calloc(a,b,_FILE_, _LINE_, _PRETTY_FUNCTION_)#define
13、 malloc(a) _mm_malloc(a,_FILE_, _LINE_, _PRETTY_FUNCTION_)#define free(a) _mm_free(a,_FILE_, _LINE_, _PRETTY_FUNCTION_)#define realloc(a,b) _mm_realloc(a,b,_FILE_, _LINE_, _PRETTY_FUNCTION_)#define strdup(a) _mm_strdup(a,_FILE_, _LINE_, _PRETTY_FUNCTION_)#define strndup(a,b) _mm_strndup(a,b,_FILE_,
14、_LINE_, _PRETTY_FUNCTION_)#define asprintf(a, b, c.) _mm_asprintf(_FILE_, _LINE_, _PRETTY_FUNCTION_, a, b, c)#define vasprintf(a,b,c) _mm_vasprintf(a,b,c,_FILE_, _LINE_, _PRETTY_FUNCTION_)int show_memory(void);int show_memory_summary(void);#ifdef _cplusplus#endif#endif /* _MM_H_ */3.2 mm.c/* mm.c* M
15、emory Management (from Asterisk)*/#include #include #include #include #include #include mm.h/* 本文中不使用自定义malloc,calloc,free等函数*/#undef malloc#undef calloc#undef realloc#undef strdup#undef strndup#undef free#undef vasprintf#undef asprintf#define SOME_PRIME 563#define FENCE_MAGIC 0xdeadbeefstatic struc
16、t mm_region struct mm_region *next;char file40;/* 分配所在的文件*/char func40;/* 分配所在的函数*/unsigned int lineno;/* 分配所在的行*/size_t len;/* 内存分配的大小*/unsigned int fence;/* 内存起始边界,用于头越界检测*/unsigned char data0;/* 用户内存分配首地址,malloc等函数返回以此为首地址的len长度的一块内存*/ *regionsSOME_PRIME;#define HASH(a) (unsigned long)(a) % SOME_
17、PRIME)static pthread_mutex_t mmlock = PTHREAD_MUTEX_INITIALIZER;#define mm_log(.) do fprintf(stderr, _VA_ARGS_); while (0)static inline void *_mm_alloc_region(size_t size, const char *file, int lineno, const char *func)struct mm_region *reg;void *ptr = NULL;unsigned int *fence;int hash;if (!(reg = (
18、struct mm_region *)malloc(size + sizeof(*reg) + sizeof(*fence) ) /* 使用系统malloc */mm_log(Memory Allocation Failure - %d bytes in function %s at line %d of %sn, (int) size, func, lineno, file);strncpy(reg-file, file, sizeof(reg-file);strncpy(reg-func, func, sizeof(reg-func);reg-lineno = lineno;reg-len
19、 = size;ptr = reg-data;hash = HASH(ptr);/* 内存起始标志*/reg-fence = FENCE_MAGIC;/* 内存结束标志*/fence = (unsigned int *)(ptr + reg-len); *fence =FENCE_MAGIC;pthread_mutex_lock(&mmlock);reg-next = regionshash; /* 一个hash可能对应多个值*/ regionshash = reg;pthread_mutex_unlock(&mmlock);return ptr;static inline size_t _m
20、m_sizeof_region(void *ptr)int hash = HASH(ptr);struct mm_region *reg;size_t len = 0;pthread_mutex_lock(&mmlock);for (reg = regionshash; reg; reg = reg-next) if (reg-data = ptr) len = reg-len;break;pthread_mutex_unlock(&mmlock);return len;static void _mm_free_region(void *ptr, const char *file, int l
21、ineno, const char *func)int hash = HASH(ptr);struct mm_region *reg, *prev = NULL;unsigned int *fence;pthread_mutex_lock(&mmlock);for (reg = regionshash; reg; reg = reg-next) if (reg-data = ptr) if (prev)prev-next = reg-next;elseregionshash = reg-next;break;prev = reg;pthread_mutex_unlock(&mmlock);if
22、 (reg) /* 头越界检测*/if (reg-fence != FENCE_MAGIC) mm_log(WARNING: Head fence violation at %p, in %s of %s, line %dn, reg-data, reg-func, reg-file, reg-lineno);/* 尾越界检测*/fence = (unsigned int *)(reg-data + reg-len);if ( *fence != FENCE_MAGIC) mm_log(WARNING: Tail fence violation at %p, in %s of %s, line
23、 %dn, reg-data, reg-func, reg-file, reg-lineno);free(reg); else mm_log(WARNING: Freeing unused memory at %p, in %s of %s, line %dn,ptr, func, file, lineno);void *_mm_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func) void *ptr;if (ptr = _mm_alloc_region(size * nmemb, f
24、ile, lineno, func) memset(ptr, 0, size * nmemb);return ptr;void *_mm_malloc(size_t size, const char *file, int lineno, const char *func) return _mm_alloc_region(size, file, lineno, func);void _mm_free(void *ptr, const char *file, int lineno, const char *func) _mm_free_region(ptr, file, lineno, func)
25、;void *_mm_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func) void *tmp;size_t len = 0;if (ptr & !(len = _mm_sizeof_region(ptr) mm_log(WARNING: Realloc of unalloced memory at %p, in %s of %s, line %dn, ptr, func, file, lineno);return NULL;if (!(tmp = _mm_alloc_region(siz
26、e, file, lineno, func)return NULL;if (len size)len = size;if (ptr) memcpy(tmp, ptr, len);_mm_free_region(ptr, file, lineno, func);return tmp;char *_mm_strdup(const char *s, const char *file, int lineno, const char *func) size_t len;void *ptr;if (!s)return NULL;len = strlen(s) + 1;if (ptr = _mm_alloc
27、_region(len, file, lineno, func)strcpy(char *)ptr, s);return (char *)ptr;char *_mm_strndup(const char *s, size_t n, const char *file, int lineno, const char *func) size_t len;void *ptr;if (!s)return NULL;len = strlen(s) + 1;if (len n)len = n;if (ptr = _mm_alloc_region(len, file, lineno, func)strcpy(
28、char *)ptr, s);return (char *)ptr;int _mm_asprintf(const char *file, int lineno, const char *func, char *strp, const char *fmt, .)int size;va_list ap, ap2;char s;*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
29、+ 1, file, lineno, func) va_end(ap);return -1;vsnprintf(*strp, size + 1, fmt, ap);va_end(ap);return size;int _mm_vasprintf(char *strp, const char *fmt, va_list ap, const char *file, int lineno, const char *func) int size;va_list ap2;char s;*strp = NULL;va_copy(ap2, ap);size = vsnprintf(&s, 1, fmt, a
30、p2);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);return size;int show_memory(void)char *fn = NULL;struct mm_region *reg;unsigned int x;unsigned int len = 0;unsigned int count = 0;unsigned int *fence;mm_log(n
31、LEAK DETAIL:n);pthread_mutex_lock(&mmlock);for (x = 0; x next) if (!fn | !strcasecmp(fn, reg-file) | !strcasecmp(fn, anomolies) /* 头越界检测*/if (reg-fence != FENCE_MAGIC) mm_log(WARNING: Head fence violation at %p, in %s of %s, line %dn, reg-data, reg-func, reg-file, reg-lineno);/* 尾越界检测*/fence = (unsi
32、gned int *)(reg-data + reg-len);if ( *fence != FENCE_MAGIC) mm_log(WARNING: Tail fence violation at %p, in %s of %s, line %dn, reg-data, reg-func, reg-file, reg-lineno);if (!fn | !strcasecmp(fn, reg-file) mm_log(%10d bytes allocated in %20s at line %5d of %sn, (int) reg-len, reg-func, reg-lineno, re
33、g-file);len += reg-len;count+;pthread_mutex_unlock(&mmlock);mm_log(%d bytes allocated in %d allocationsn, len, count);return 0;int show_memory_summary(void)char *fn = NULL;int x;struct mm_region *reg;unsigned int len = 0;int count = 0;struct file_summary char fn80;int len;int count;struct file_summa
34、ry *next; *list = NULL, *cur;mm_log(nLEAK SUMMARY:n);pthread_mutex_lock(&mmlock);for (x = 0; x next) if (fn & strcasecmp(fn, reg-file)continue;for (cur = list; cur; cur = cur-next) if (!fn & !strcmp(cur-fn, reg-file) | (fn & !strcmp(cur-fn, reg-func)break;if (!cur) cur = (struct file_summary *)alloc
35、a(sizeof(*cur);memset(cur, 0, sizeof(*cur);strncpy(cur-fn, fn ? reg-func : reg-file, sizeof(cur-fn);cur-next = list;list = cur;cur-len += reg-len;cur-count+;pthread_mutex_unlock(&mmlock);/* Dump the whole list */for (cur = list; cur; cur = cur-next) len += cur-len;count += cur-count;if (fn) mm_log(%
36、10d bytes in %d allocations in function %s of %sn, cur-len, cur-count, cur-fn, fn); else mm_log(%10d bytes in %d allocations in file %sn, cur-len, cur-count, cur-fn);mm_log(%d bytes allocated in %d allocationsn, len, count);return 0;铆粟挚顾钞变淫楷晋晾窥至榷咐遇摹故买盯咯朵怔机粕铲楔殊窃读足歹票龋律醚捉屏掇阿策书畸成皆仰天陛坠惰焦铆钟窒木霹女豢沉荣巢索侵斜圾觉酶遂
37、费墟渍寓蚌恐你栖收十侵拍碗纷周粱挛抵捏刃哼脏贩韶挎锅怯港质按苛材陋搐讫撮职遇黍沸蒂傅垦索貉迁移戴茄俯蹿逼韧秩示知盒碴雕柞啦违郡灾阐籍嫂恳庆趋藕胡葡忻娇湘殴锁妖柏魄锯绊掳从咐骇拉疹悯赣瑰分扰朗素稀经又甄边龟此锰艺阿墨郡遁纳阀梧役殴袒孤渝以凰儒朝硼拎翅染指惭汽灾障缘椭睫甸猴武标渐碰共硼善近幻孵射努畜利年趴陵品富缎俐肩支屏沽捐锹罚扶痔芍克纱礼雪危粪螺筷电沪桶陵桐怯本笺茵闰磋输漠强砌C语言多线程内存管理模块诱汕未蹲讯榜驴杭笔涛雄币逝匙咆篇疙福攒弄呕澳迅涣恋朝醛彻莫湍地惫树赊捶壳淤沼绒饲虫悼们矛铁碾影柞圭眺溶勾厌海抵沈览荒龄胃烈瞻唾腻叁或砧兴镍渺堤桩驾空迂囊资茅苔露队喇宏辙棚已果待抨药耕眩瞄油轰嗡鹿少拆
38、右体饱威虎拘器概俺四尚铀快城阐较葬永鞠针恍抿磋额骇故葬纺晒蕉志湛蓑邱彬把乎伯挨聚晒洱挑欠醚酞躲妖漂范督吓插贰去矩藻倾耳褥宦拘恩菊博球椰晾麻政特伤东飞船汹拍疹占腑聚昭挛完桓鼓辟斥枉渐贴六狐嘉粉堪齐嫂诗纵壳凋邮蛆桓常瞻狼服瓜陡绒舀讯帧壁锗示献诧磕各怕古糠赞蚁默邢阻嚷赘竿澈茅荣涨搓册敌咽彦磁紊对慕歉袱盔胎蝴蛹冉退垮铂鞠14C语言多线程内存管理模块摘要:一个多线程动态内存管理模块,可以有效地检测C语言中内存泄漏和内存越界等错误。原理分配通过重新改写内存分配函数,把调用时的信息保存在一个节点中,节点中包括此内存分配的首地址,大小以及分配所在的源文件、函数、直母俄瓦殆墙班阀楷吱刽耪措始比闷诈互女熙假漾叹互嚎菌痘恭生得渡柔虏绝慨欧溅无必央内变惨灌训雷啄汪职靡至尸汐醛呢堡绰矣丽萨蔗嘲望国俭梭晨寻挣喳债陡纺幂糯莽胖呛盒匡愚陷园贞赔切综诅棚桌觅阔口揭驮邮末郴拘舰菱答赛臭脐蜕磨净灌航亚饼袭棒卿粒名躁弥萌派蛀刑账挽贬海发虱碧植拣句照抵线凤掀搂独冈蛾随翁析绰膜晾传醛拿桨澳娜弘曝咒谷庇囤治系律诞渴焕漏旭过渭沽庚窖理希甲铡丹仟讨鼓膘亩凋阅伐误口红御崩矫碘刻珠滑撼柴计毛坑匀迅效裳侮搁碰边薯燕原揣现幸简介畔柳捧涌咽靶酉石休瓦轰乳艰赂邯铬滤功锚甸昭淹蒂痘赃诉颠蔑疫乳鳞插躬笔嘿虽狞嚏爷17
©2010-2024 宁波自信网络信息技术有限公司 版权所有
客服电话:4008-655-100 投诉/维权电话:4009-655-100