给内存泄漏打个补丁

     内存泄漏,开发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函数定期的检测内存,这样就有效解决了因为内存泄漏给游戏带来灾难性的后果了。

这个补丁真是我迫不得已才使用的,现在把它共享给大家,希望能对大家有所帮助。
如果大家有什么意见和建议请告诉我。谢谢
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值