#define HASHTABLE_LEN 8 #define MAX_LEN 512 typedef struct HASHTABLE { void *hashkeyaddr;//存储所分配的内存的地址 int fileline;//代码所在在的文件行数 char filename[MAX_LEN];//代码所在爱的文件名 }HashTable; // 版权所有 (C)2007, ***(成都)有限公司。 // // 描述: //6.6:hash表 //在项目应用中,我们很可能在动态分配内存后忘了释放,当工程大到一定程序,对内存泄露的查找就非常困难, //所以我们一般是用一个资源管理的模块来对分配的内存进行统一管理。 //管理的办法是在内存分配时把内存的地址记录在一个集合中,在内存释放的时候,把这个地址从集合中移除。 //在程序结束的时候检查集合是还有没有成员,有的话,就是有内存没有释放。 //这个集合我们可以用链表来实现,但在实际应用中,内存的分配释放不仅多而且频繁, //而在链表大了之后的查寻效率非常抵的。所以在这里这个集合用Hash表来实现。 //要求: //1、实现一个宽度为8(用宏表示)的Hash表的插入,查找,删除函数。 //1、分别用 lib_malloc,lib_free两个函数来封装系统的malloc,free函数,在lib_malloc时把分配的内存的地址、 //在代码中哪个文件(__FILE__见msdn)哪一行(__LINE__见msdn)分配的记录到Hash表中,在lib_free中把对应的内存地址等信息从hash表中移去。 //2、在主函数中用lib_malloc申请多段内存,并释放部分。在程序的最后打印出未释放的内存的地址,以及在哪儿分配的等信息。 //3、Hash表中元素尽可能的均匀分布 // 作者:陈进宇chenjinyu_china@yeah.net // 日期:start:2009/3/17 end:2009/3/17 #include <iostream> #include "HashList_new.h" #define MYMALLOC(LEN) lib_malloc(LEN,__FILE__ , __LINE__) using namespace std; // 初始化hash表 void Initiate(); // 查找要的键值 int SearchHashItem(void *searchkey); // 插入一个hash值 int InsertHashItem(void *address); //创建一个空间用以接受变量的地址 //void lib_malloc(void *address,char* filename, int line); void *lib_malloc(int size,char *filename ,int fileline); void lib_free(void *pAddress); // 释放空间 //void lib_free(void *searchkey); // 打印hash表中的地址,所在文件,行号信息 void Print(); HashTable hasharr[HASHTABLE_LEN]; void main() { Initiate(); int *pInt = (int *)MYMALLOC(sizeof(int)); if(pInt != NULL) { *pInt = 65535; printf("/nThe value --->%d/n",*pInt); } char *pCh = (char *)MYMALLOC(sizeof(char)); if(pCh != NULL) { *pCh = 'b'; printf("/nThe value --->%c/n",*pCh); } char *pStr = (char *)MYMALLOC(sizeof(char)*20); if(pStr != NULL) { strcpy(pStr,"I love China!"); printf("/nThe value --->%s/n",pStr); } short *pShort = (short *)MYMALLOC(sizeof(short)); if(pShort != NULL) { *pShort = 32767; printf("/nThe value --->%d/n",*pShort); } Print(); lib_free(pShort); Print(); } /// <summary> /// 初始化hash表 /// </summary> /// <returns>无返回值</returns> void Initiate() { for(int i = 0; i < HASHTABLE_LEN ;i++) { hasharr[i].hashkeyaddr = NULL; hasharr[i].fileline = 0; strcpy(hasharr[i].filename,""); } } /// <summary> /// 查找要的键值 /// </summary> /// <param name="searchkey">[in] void *searchkey:这里是变量的地址。</param> /// <returns>返回的是该变量地址所在的hash表中的位置,-1则在hash表中没有此key</returns> int SearchHashItem(void *searchkey) { int addr = (int)searchkey % HASHTABLE_LEN; int i = addr,j = addr; if(hasharr[i].hashkeyaddr == searchkey) { return i; } else { while((i >= 0 && i < 8) || (j >= 0 && j < 8 )) { i++; if(hasharr[i].hashkeyaddr != NULL && hasharr[i].hashkeyaddr == searchkey) { return i; } j--; if(hasharr[j].hashkeyaddr != NULL && hasharr[j].hashkeyaddr == searchkey) { return j; } } } return -1; } /// <summary> /// 插入一个hash值 /// </summary> /// <param name="address">[in] void *searchkey:这里的变量的地址。</param> /// <returns>返回的是插入的位置</returns> int InsertHashItem(void *address) { int addr = (int)address % HASHTABLE_LEN; int i = addr,j = addr; if(hasharr[i].hashkeyaddr == NULL ) { return addr; } else { while( (i >= 0 && i < 8) || (j >= 0 && j < 8) ) { i = i + 1; if(hasharr[i].hashkeyaddr == NULL) { return i; } j = j + 1; if(hasharr[j].hashkeyaddr == NULL) { return j; } } } return -1; } /// <summary> ///创建一个空间用以接受变量的地址 /// </summary> /// <param name="address">[in] void *address:树的根。</param> /// <param name="filename">[in] char* filename:树的根。</param> /// <param name="line">[in] int line:树的根。</param> /// <returns>无返回值</returns> void *lib_malloc(int size,char *filename, int fileline) { void *pAddr = malloc(size); int i = InsertHashItem(pAddr); if(i < 0) { printf("sorry,hashtable is full"); } else { hasharr[i].hashkeyaddr = pAddr; hasharr[i].fileline = fileline; strcpy(hasharr[i].filename,filename); //printf("malloc success!/n"); } return pAddr; } /// <summary> /// 释放空间 /// </summary> /// <param name="searchkey">[in] void *searchkey:要删除的key。</param> /// <returns>无返回值</returns> void lib_free(void *pAddress) { int i = SearchHashItem(pAddress); if(i > 0) { free(pAddress); hasharr[i].hashkeyaddr = NULL; hasharr[i].fileline = 0; strcpy(hasharr[i].filename,""); printf("/ndelete success!/n"); } else { printf("not found this key!"); } } /// <summary> /// 打印hash表中的地址,所在文件,行号信息 /// </summary> /// <returns>无返回值</returns> void Print() { for(int i = 0; i < HASHTABLE_LEN; i++) { if(hasharr[i].hashkeyaddr != NULL) printf("/nThis address is %d /n This FILE is %s /n This LINE is %d/n",(int)hasharr[i].hashkeyaddr,hasharr[i].filename,hasharr[i].fileline); } }