Developer forums (C::B DEVELOPMENT STRICTLY!) > Development

BUG: Memory Leak at cbProject::VirtualFolderAdded

<< < (3/3)

lights_joy:

--- Quote from: MortenMacFly on January 22, 2014, 06:18:01 pm ---
--- Quote from: lights_joy on January 22, 2014, 03:55:48 pm ---the wxTreeItemData object will be destroyed only when it's attached to a FileTreeItem,
but in the code here, the ftd is not attached to any FileTreeItem, so it will NOT freed automatically.

--- End quote ---
What do you think does "AddTreeNode(tree, foldername, m_ProjectNode, true, FileTreeData::ftdkVirtualFolder, true, vfldIdx, ftd);" do?

--- End quote ---

Let's see the AddTreeNode function:


--- Code: ---wxTreeItemId cbProject::AddTreeNode(wxTreeCtrl*                    tree,
                                    const wxString&                text,
                                    const wxTreeItemId&            parent,
                                    bool                           useFolders,
                                    FileTreeData::FileTreeDataKind folders_kind,
                                    bool                           compiles,
                                    int                            image,
                                    FileTreeData*                  data)
{
    // see if the text contains any path info, e.g. plugins/compilergcc/compilergcc.cpp
    // in that case, take the first element (plugins in this example), create a sub-folder
    // with the same name and recurse with the result...

    wxTreeItemId ret;

    if (text.IsEmpty())
        return ret;

    wxString path = text;

    // special case for windows and files on a different drive
    if ( platform::windows && (path.Length() > 1) && (path.GetChar(1) == _T(':')) )
        path.Remove(1, 1);

    // avoid empty node names in case of UNC paths, then, at least the first two chars are slashes
    while ((path.Length() > 1) && (path.GetChar(0) == _T('\\') || path.GetChar(0) == _T('/')) )
        path.Remove(0, 1);

    if (path.IsEmpty())
        return ret;

    int pos = path.Find(_T('/'));
    if (pos == -1)
        pos = path.Find(_T('\\'));
    if (useFolders && pos >= 0)
    {
        // ok, we got it. now split it up and re-curse
        wxString folder = path.Left(pos);
        // avoid consecutive path separators
        while (path.GetChar(pos + 1) == _T('/') || path.GetChar(pos + 1) == _T('\\'))
            ++pos;
        path = path.Right(path.Length() - pos - 1);

        wxTreeItemIdValue cookie = 0;

        wxTreeItemId newparent = tree->GetFirstChild(parent, cookie);
        while (newparent)
        {
            wxString itemText = tree->GetItemText(newparent);
            if (itemText.Matches(folder))
                break;
            newparent = tree->GetNextChild(parent, cookie);
        }

        if (!newparent)
        {
            // in order not to override wxTreeCtrl to sort alphabetically but the
            // folders be always on top, we just search here where to put the new folder...
            int fldIdx  = Manager::Get()->GetProjectManager()->FolderIconIndex();
            int vfldIdx = Manager::Get()->GetProjectManager()->VirtualFolderIconIndex();

            newparent = FindNodeToInsertAfter(tree, folder, parent, true);

            FileTreeData* ftd = new FileTreeData(*data);
            ftd->SetKind(folders_kind);
            if (folders_kind != FileTreeData::ftdkVirtualFolder)
                ftd->SetFolder(m_CommonTopLevelPath + GetRelativeFolderPath(tree, parent) + folder + wxFILE_SEP_PATH);
            else
                ftd->SetFolder(GetRelativeFolderPath(tree, parent) + folder + wxFILE_SEP_PATH);
            ftd->SetProjectFile(0);
            int idx = folders_kind != FileTreeData::ftdkVirtualFolder ? fldIdx : vfldIdx;
            newparent = tree->InsertItem(parent, newparent, folder, idx, idx, ftd);
        }
        ret = AddTreeNode(tree, path, newparent, true, folders_kind, compiles, image, data);
    }
    else
    {
        ret = tree->AppendItem(parent, text, image, image, data);
        if (!compiles)
            tree->SetItemTextColour(ret, wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT));
    }
    return ret;
}
--- End code ---
i created a virtual fold named 'test4', the first time called this function, the input parameter was:
   text = "test4\"
   useFolders = true
   data = a new allocated pointer
the following code will be executed:
            FileTreeData* ftd = new FileTreeData(*data);
            ftd->SetKind(folders_kind);
            if (folders_kind != FileTreeData::ftdkVirtualFolder)
                ftd->SetFolder(m_CommonTopLevelPath + GetRelativeFolderPath(tree, parent) + folder + wxFILE_SEP_PATH);
            else
                ftd->SetFolder(GetRelativeFolderPath(tree, parent) + folder + wxFILE_SEP_PATH);
            ftd->SetProjectFile(0);
            int idx = folders_kind != FileTreeData::ftdkVirtualFolder ? fldIdx : vfldIdx;
            newparent = tree->InsertItem(parent, newparent, folder, idx, idx, ftd);

the new ftd was attached to the tree, but data NOT            
then call AddTreeNode second time:
        ret = AddTreeNode(tree, path, newparent, true, folders_kind, compiles, image, data);
the input parameter was
   text = ""
   useFolders = true
   data = a pointer that was passed at first time

then because text is a blank string, it will return quickly:
    if (text.IsEmpty())
        return ret;

you see, the data pointer input first time was NOT attached to any tree item, so this is the problem!

dmoore:
So this code


--- Code: ---            FileTreeData* ftd = new FileTreeData(*data);
...
            newparent = tree->InsertItem(parent, newparent, folder, idx, idx, ftd);

--- End code ---

Is copying the contents of data into a new structure, but the chunk pointed to by data never gets deleted because it is the copy (ftd) that gets attached to the tree?

dmoore:

--- Quote from: lights_joy on January 23, 2014, 03:21:03 am ---
--- Code: ---    if (text.IsEmpty())
        return ret;

--- End code ---

--- End quote ---

yes, and I see that this chunk is problematic too because (presumably) data is never deleted by the caller.

Navigation

[0] Message Index

[*] Previous page

Go to full version