內存泄漏,開發C/C++的程序員再熟悉不過了,用一場惡夢來形容它一點也不爲過。
不巧,我就碰到了這樣的一場惡夢,我在移植一款手機遊戲上遇到了這樣的問題,當然原來的遊戲代碼並不是我寫的,是誰寫的我也不知道,但是確實出現了內存泄漏的問題。內存泄漏的字節並不多,但是積累起來就要命了,而且是在手機上,內存並不富裕。更可怕的是這個問題幾乎無從下手。
這是個益智類遊戲,是一個3個球成三角就可以消掉的遊戲,遊戲代碼中用了很多結構體和鏈表,樹等數據結構,我根本無法知道,代碼中分配的內存是在哪裏釋放,而且我也不知道這個地方該不該釋放,是否還有別的指針指向它。時間不允許我再過多的研究代碼的細節,我只能硬着頭皮給這個程序打上一個“補丁”了。
這個代碼是使用C語言寫的,下面列出部分的代碼以供參考。
首先我定義了一個鏈表的節點
typedef struct _TestMem
{
U8 *m_pMemD;//保存分配的地址指針
struct _TestMem *m_pNext;
}TestMem;
並定義瞭如下的兩個變量
TestMem g_Mem;
TestMem *g_pLast;//指向鏈表的最後一個節點
接下來重寫了內存分配很內存回收的函數
void* MALLOC_Ex(uint32 dwSize)
{
void *pVoid = MALLOC(dwSize);
if(g_pLast)
{
g_pLast->m_pNext = (TestMem*)MALLOC(sizeof(TestMem));
g_pLast = g_pLast->m_pNext;
g_pLast->m_pMemD = pVoid;
g_pLast->m_pNext = NULL;
}
return pVoid;
}
void FREE_Ex(void *po)
{
TestMem *pMid;
TestMem *pDel;
pMid = &g_Mem;
while(pMid->m_pNext)
{
pDel = pMid->m_pNext;
if(pDel->m_pMemD == po)
{
if(g_pLast == pDel)g_pLast = pMid;
pMid->m_pNext = pDel->m_pNext;
FREE(pDel);
break;
}
pMid = pMid->m_pNext;
}
FREE(po);
}
使用這兩個函數替換原來代碼中原有的函數,當然只是替換相關的函數
最後定義初始化和回收的函數
void InitTestMem()
{
g_Mem.m_pMemD = NULL;
g_Mem.m_pNext = NULL;
g_pLast = &g_Mem;
}
void ReleaseTestMem()
{
TestMem *pMid;
TestMem *pDel;
pMid = g_Mem.m_pNext;
while(pMid)
{
if(pMid->m_pMemD)FREE(pMid->m_pMemD);
pDel = pMid;
pMid = pMid->m_pNext;
FREE(pDel);
}
InitTestMem();
}
把InitTestMem函數放到遊戲的初始化部分,ReleaseTestMem函數放到原有代碼的釋放結構體內存的地方(也就是通過當前關,Gameover的地方),用來釋放沒有釋放的內存,也就是那些內存泄漏的部分。
這就基本完成了這個補丁。
但是還有個問題,就是如果玩家始終沒有過關或Gameover的話,那麼就可能無法調用ReleaseTestMem函數,那麼內存也會一直泄漏下去,直到消耗掉所有的內存。因此這裏我又添加了一段代碼
void AutoDelMem()
{
U32 mem;
mem = 返回當前的FREE內存
if(mem <= 20)//當前內存小於20時釋放一部分泄漏內存
{
int count;
TestMem *pMid;
TestMem *pDel;
pMid = g_Mem.m_pNext;
count = 100;//100可根據具體的情況來調整,因爲遊戲在玩一段時間後,內存泄漏了很多了,這樣就可以安全的釋放最先泄漏的一部分內存,這裏存在一定的風險,不過,還好這個遊戲正好符合這個條件
while(count > 0 && pMid)
{
if(pMid->m_pMemD)FREE(pMid->m_pMemD);
pDel = pMid;
pMid = pMid->m_pNext;
FREE(pDel);
--count;
}
g_Mem.m_pNext = pMid;
if(!pMid)g_pLast = &g_Mem;
}
}
使用AutoDelMem函數定期的檢測內存,這樣就有效解決了因爲內存泄漏給遊戲帶來災難性的後果了。
這個補丁真是我迫不得已才使用的,現在把它共享給大家,希望能對大家有所幫助。
如果大家有什麼意見和建議請告訴我。謝謝
2007年05月22日 22:21:00