簡體   English   中英

CArray的內存泄漏

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM