2013-05-31 126 views
1

在我的例子我正在努力我有以下情況,一個父 - 子關係配置深達4層深存儲在數據庫中。每個項目都有'id'和'name'屬性。因爲我的英語不太好,畫面可能會有所幫助:
my tree內存泄漏與CArray

因此,基本上,每個父母能擁有孩子的數量(除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); 
     } 
    } 
} 

只有在這個功能在使用「新」運營商。

我第一次調用這個函數是從'MyView'用params'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工作(是的,我知道它已經過時了,但它是特殊情況)。

回答

0

父母/孩子的東西看起來不錯,但我寧願把完整的銷燬東西放到TEST_EX_REASON的析構函數中。在我看來,這更安全,更清楚。

當結果不包含行時,我看到泄漏。 在這種情況下,您以前不調用mysql_free_result(result)就會返回。

+0

謝謝@ user2328447,就是這樣。我不相信,我把那個留下了。我一直在尋找分配和釋放內存有什麼問題,它並沒有跨越我的想法,即mysql_free_result()是發生泄漏的地方。我想這是其中一天......再次感謝。 – cagi