[英]Memory leaks with CArray
在示例中,我正在處理以下情況,即父級-子級關系配置,最多可存儲到數據庫中的4個級別。 每個項目都有“ id”和“ name”屬性。 因為我的英語不太好,所以圖片可能會有所幫助:
因此,基本上每個父母都可以有多個孩子(4級父母除外,它沒有孩子,深度為4是有限的)。 我需要一個對象來將“樹”存儲在內存中。 我決定使用它們的結構和數組。
struct TEST_EXT_REASON
{
int id;
CString name;
CArray<TEST_EXT_REASON*, TEST_EXT_REASON*> m_arrChildren;
TEST_EXT_REASON::TEST_EXT_REASON()
{
id=0;
name="";
}
};
CArray<TEST_EXT_REASON*, TEST_EXT_REASON*> m_arrTestExtReason;
應用程序關閉時出現內存泄漏問題。
這是我的代碼片段,用於填充結構:
void FillTestLevels(CMyView* pObject, TEST_EXT_REASON* pParent, int level, CString query)
{
int err = mysql_query( myData1, query.GetBuffer(0), NULL );
if(err) {
AfxMessageBox(mysql_error(myData1)) ;
return;
}
MYSQL_RES * result;
MYSQL_ROW cur;
result = mysql_store_result( myData1 ) ;
if (!result) return;
int cnt = mysql_num_rows(result);
if(cnt==0) return;
int id;
char* desc;
while ((cur = mysql_fetch_row(result)))
{
if (cur[0]) id=atoi((char *)cur[0]);
else id=0;
if (cur[1]) desc = (char *)cur[1];
else desc = "";
TEST_EXT_REASON* pLevel = new TEST_EXT_REASON;
pLevel->id = id;
pLevel->name = desc;
if(!pParent && level==1) pObject->m_arrTestExtReason.Add(pLevel);
else pParent->m_arrChildren.Add(pLevel);
}
mysql_free_result(result);
if(level==4) return;
if(!pParent && level==1)
{
for (int i=0; i<=pObject->m_arrTestExtReason.GetUpperBound(); i++)
{
TEST_EXT_REASON* pLevel = pObject->m_arrTestExtReason.GetAt(i);
CString q_str;
q_str.Format("SELECT id,name FROM reason_ext_lev WHERE id_parent = %d ORDER BY name", pLevel->id);
FillTestLevels(pObject, pLevel, level+1, q_str);
}
}
else
{
for (int i=0; i<=pParent->m_arrChildren.GetUpperBound(); i++)
{
TEST_EXT_REASON* pLevel = pParent->m_arrChildren.GetAt(i);
CString q_str;
q_str.Format("SELECT id,name FROM reason_ext_lev WHERE id_parent = %d ORDER BY name", pLevel->id);
FillTestLevels(pObject, pLevel, level+1, q_str);
}
}
}
僅在此功能中使用“ new”運算符。
第一次調用此函數是從“ MyView”使用參數“ pParent”,NULL和“ level” 1進行的,此后它在工作中遞歸(將其自身填充到末尾)。
pObject->DeleteTestExtReasonArrays();
str.Format("SELECT id,name FROM reason_ext_lev WHERE id_cfg = %d AND id_parent = 0 ORDER BY name", pObject-m_nConfigId);
FillTestLevels(pObject, NULL, 1, str);
這就是釋放內存的方式(在DeleteTestExtReasonArrays()中):
void CMyView::DeleteTestExtReasonArrays()
{
int size = m_arrTestExtReason.GetSize();
for (int i=size-1; i>=0; i--)
{
TEST_EXT_REASON* pTmp = m_arrTestExtReason.GetAt(i);
if(pTmp->m_arrChildren.GetSize()>0)
DeleteTestExtReasonChildren(pTmp);
m_arrTestExtReason.RemoveAt(i,1);
delete pTmp;
pTmp = NULL;
}
m_arrTestExtReason.RemoveAll();//I don't need this realy
}
void CMyView::DeleteTestExtReasonChildren(TEST_EXT_REASON* pParent)
{
int size = pParent->m_arrChildren.GetSize();
for (int i=size-1; i>=0; i--)
{
TEST_EXT_REASON* pTmp = pParent->m_arrChildren.GetAt(i);
if(pTmp->m_arrChildren.GetSize()>0)
DeleteTestExtReasonChildren(pTmp);
pParent->m_arrChildren.RemoveAt(i,1);
delete pTmp;
pTmp=NULL;
}
pParent->m_arrChildren.RemoveAll();
}
唯一的問題是我遇到內存泄漏,找不到位置。 每個項目都已填充,最后發布。 我正在VS6中工作(是的,我知道它已經過時了,但這是特例)。
盡管我希望將完整的銷毀內容放入TEST_EX_REASON的析構函數中,但父母/孩子的內容對我來說看起來還不錯。 我認為,這更安全,更明確。
當結果不包含行時,我會看到泄漏。 在這種情況下,您無需事先調用mysql_free_result(result)就可以返回。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.