軟件測試開發技術數據結構與算法:內存泄漏檢查[1] 軟件測試工具
關鍵字:數據庫設計使用引用計數的方法實現的內存垃圾回收不能自動回收循環引用的內存,循環引用的內存需要使用手工進行釋放,但手工釋放很可能由于編程人員的失誤導致內存泄漏,所以必須檢查是否存在內存泄漏。要完成這項任務,只要在程序退出時檢查一下哈希表中還有哪些內存的引用計數不為0,就可以知道有哪些內存還沒有被釋放,內存沒有被釋放的原因有以下兩種。
①內存是供全局使用的,必須等到要退出時才能釋放;
②內存中有循環引用,導致不能釋放。
還需要知道哈希表中保存的內存地址指向的內存是在程序的哪一行分配的,才能定位到具體發生泄漏的位置。C語言中有一個宏可以獲取源程序中的行號,下面就用這個宏來實現內存泄漏檢查。
內存泄漏只是在軟件的DEBUG版本才需要用到,因此下面就來設計一個DEBUG版本的內存垃圾回收。
首先要修改內存中需要保存的數據,除了保存引用計數外,還需要保存分配這塊內存的源程序文件名和行號,還要保存分配內存的大小信息。為方便起見,可以將引用計數和內存大小保存在分配內存的頭部,行號和文件名保存在分配內存的尾部。
關于獲取源程序文件名和行號,可以使用宏_FILE_和_LINE_來獲取,要注意的是,_LINE_和_FILE_是調用它們的地方的源文件名和行號,如果簡單地在GC_Malloc()函數中使用這兩個宏,那么所有調用GC_Malloc()函數的地方獲得的源文件名和行號都是GC_Malloc()函數的源文件名和行號,所有獲取的源文件名和行號均相同,顯然達不到預想的目的。
預想的目的是為了獲取調用GC_Malloc()處的源文件名和行號,因此需要將GC_Malloc()函數定義成宏,這樣在調用它的地方就會將編碼展開,便能得到正確的調用GC_Malloc()處的源文件名和行號,有助于確認發生內存泄漏的位置及原因。
通常只要在程序的調試版本中檢查內存泄漏就可以了,修改后對應的GC_Malloc()和GC_Free()函數如下。
#ifdef_DEBUG
#defineGC_Malloc(size)
{
void*p;
INT*q;
char*psz;
p=malloc(size+DOUBLE_INT_LEN+INT_LEN+strlen(__FILE__)+1);
if(p==NULL)
{
GC_Collect();
p=malloc(size+DOUBLE_INT_LEN+INT_LEN+strlen(__FILE__)+1);
if(p==NULL)
{
returnNULL;
}
}
HashTable_Insert(g_pTable,p,HashInt);
*((INT*)p)=0;
*((INT*)p+1)=size;
q=(INT*)((char*p)+size+DOUBLE_INT_LEN);
*q=__LINE__;
psz=(char*)p+size+DOUBLE_INT_LEN+INT_LEN;
strcpy(psz,__FILE__);
return(void*)((char*)p+DOUBLE_INT_LEN);
}
/** 垃圾內存收集算法的內存釋放函數
@param void*p——要釋放的內存地址
@return void——無
*/
voidGC_Free(void*p)
{
void*pFree=(void*)((char*)p-DOUBLE_INT_LEN);
free(pFree);
}
#endif
下面就來實現內存泄漏的檢查。內存泄漏檢查只需要在程序退出時檢查哪些內存的引用計數不為0,只要對哈希表做一個遍歷操作就可以獲取哪些內存的引用計數不為0,編碼如下。
/** 垃圾內存收集算法的內存泄漏檢查函數
@return void——無
*/
文章來源于領測軟件測試網 http://www.kjueaiud.com/