[英]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.