资源描述
优化代码以避免堆存储碎片
#define MSG_SIZE (100 * sizeof(AECHAR))
static void CMyApp_FragmentTheHeap(CMyApp * pme, AECHAR * p1,
AECHAR * p2)
{
byte *pDest,*pTemp;
AECHAR szFormat[10];
STR_TO_WSTR("%s%s",szFormat,sizeof(szFormat));
pTemp = (AECHAR *)MALLOC(MSG_SIZE);
if(!pTemp)
return;
WSPRINTF(pTemp,MSG_SIZE,szFormat,p1,p2);
i = (WSTRLEN(pTemp) + 1) * sizeof(AECHAR);
pDest = WSTRDUP(pTemp);
FREE(pTemp);
...
}
此代码有什么问题?
尽管此代码实际上在初次分配时检查 NULL,但它会导致堆中出现存储碎片(即“孔”)。 这可能使以后的分配无故失败。 pTemp 的内存仅在分配新值 pDest 后释放。 更佳的解决方案如下所示:
#define MSG_SIZE (100 * sizeof(AECHAR))
static void CMyApp_FragmentTheHeap(CMyApp * pme, AECHAR * p1,
AECHAR * p2)
{
byte * pDest;
int nLen;
if(!p1 || !p2)
return;
pDest = (AECHAR *)MALLOC((WSTRLEN(p1) + WSTRLEN(p2) + 1) * sizeof(AECHAR));
if(!pDest)
return;
WSTRCPY(pDest, p1);
WSTRCAT(pDest, p2);
...
}
所有这些错误都非常严重。 简言之,它们将一个可用于显示消息框的简单函数转换成一个引起异常的函数!
检查 NULL 和不必要的分配
Static void CMyApp_HowManyMistakesCanIMakeInOneFunction(
CmyApp *pme,const AECHAR * pszError)
{
AECHAR * pMsg;
int i;
i = (WSTRLEN(pszError) + 1) * sizeof(AECHAR);
pMsg = (AECHAR *)MALLOC(i);
WSTRCPY(pMsg,pszError);
ISHELL_MessageBox(pme->a.m_pIShell, pMsg,...);
FREE(pMsg);
}
此代码有什么问题?
此函数中有几个非常严重的错误。 它包括:
· 无法检查确保 pszError 在使用前为 NULL
· 无法检查 MALLOC 的 NULL 返回值
· 不需要时分配 pMsg。 “pszError”值可以直接传递给 ISHELL_MessageBox
所有这些错误都非常严重。 简言之,它们将一个可用于显示消息框的简单函数转换成一个失效的函数。
BREW™ 应用程序必须检查内存分配例程的返回值 NULL、返回类实例的值等。
不合理地分配大块
static void CMyApp_AllocateTooMuch(CMyApp * pme,
const byte * pIn, int nSize)
{
int nNewSize;
nNewSize = pme->m_nBuffFilled + nSize;
if(pme->m_nBuffSize < nNewSize){
if(nNewSize < 0x4000)
pme->m_nBuffSize = 0x4000;
else
pme->m_nBuffSize = nNewSize + 0X4000;
while((pme->m_pBuff = REALLOC(pme->m_pBuff,
pme->m_nBuffSize)) == NULL)
pme->m_nBuffSize -= 0x100;
if(pme->m_nBuffSize < nNewSize)
return;
}
}
...
}
此代码有什么问题?
此代码不确定必需多少字节,而是增加额外分配的字节,以期避免未来的分配。 虽然这在“额外”分配的大小合理时是可以接受的,但本例中的额外开销远远超出了 BREW™ 中的合理分配大小。 更佳的解决方案如下所示:
static void CMyApp_AllocateTooMuch(CMyApp * pme, const byte * pIn,
int nSize)
{
int nNewSize;
nNewSize = pme->m_nBuffSize + nSize;
pme->m_pBuff = (byte *)REALLOC(pme->m_pBuff, nNewSize);
if(!pme->m_pBuff)
return;
...
pme->m_nBuffSize = nNewSize;
}
展开阅读全文