shared_ptrs和内存泄漏

时间:2016-02-17 17:43:37

标签: c++ c++11 memory-leaks

我有一个用C ++做的项目(此外,我不得不使用C ++ 11中的一些东西,特别是:自定义迭代器,智能指针和计时器),它们构造特定字符串的后缀树。当谈到构建树时,我认为我做得很好 - 我有一棵合适的树,施工时间和搜索时间看起来相当不错,而且这不是一个问题。但是,我知道我弄乱了我的TNode结构 - 我没有使用weak_ptrs,因此在我的树类中,我必须构建巨大的析构函数,在每个节点上行走并强行删除任何连接。

无论如何,我使用Deleaker检查可能的内存泄漏。没有#" abracadabra"字。不幸的是,它发现了一些泄漏(" lorem ipsum(...)"。他们中的大多数都与创建新节点相关联,我无法理解我的问题所在。我根本就没有得到它 - 当程序结束时,似乎每个节点都被破坏了。我在哪里弄错了?

Node.h:

#pragma once
#include <algorithm>
#include <vector>
#include <memory>
#include <Windows.h>

#define INF 1<<30

struct TNode : public std::enable_shared_from_this<TNode>{
    long int indexStart;
    long int indexEnd;
    std::vector<std::shared_ptr<TNode>> children;
    std::shared_ptr<TNode> suffixLink;
    int count;
    TNode(long int pIndexStart, int pCount) {
        indexStart = pIndexStart;
        indexEnd = INF;
        children.clear();
        suffixLink = nullptr;
        count = pCount;
    }
    ~TNode() {
        //OutputDebugString(L"node dies\n");
    }
    int EdgeLength(long int pos) {
        return min(indexEnd, pos+1) - indexStart;
    }
};

tree.h中

#pragma once
#include <memory>
#include <vector>
#include "IChildIterator.h"
#include "Node.h"

class CTree
{
public:
    CTree();
    ~CTree();
    void LoadString(std::string* newString);
    void CreateTree();
    bool FindPhrase(std::string* toFind);
    void PrintSuffix(std::vector<long> indexes);
    std::shared_ptr<TNode> GetRoot();

private:
    std::shared_ptr<TNode>  root;
    std::shared_ptr<TNode>  activeNode;
    long int                activeEdge;
    long int                activeLength;
    std::string*            string;
    std::shared_ptr<TNode>  lastAddedNode;
    long int                position;
    long int                remainder;
    int                     count;

    void AddSuffixLink(std::shared_ptr<TNode> node);
    bool WalkDown(std::shared_ptr<TNode> node);
    void ExtendTree();
    char GetActiveEdge();
};

tree.cpp

#include "stdafx.h"
#include "Tree.h"


CTree::CTree()
{
    std::shared_ptr<TNode> nowy(new TNode(-1, -1));
    root = activeNode = nowy;
    activeEdge = activeLength = 0;
    lastAddedNode = nowy;
    position = -1;
    remainder = 0;
    count = 0;
    string = nullptr;
}


CTree::~CTree()
{
    if (string) {
        delete string;
    }
    std::vector<IChildIterator> iterstack;
    iterstack.resize(0);
    IChildIterator child(root, true);
    while (true) {
        if (0 == (*child)->children.size()) {
            if (iterstack.size() == 0)
                break;
            child = iterstack.back();
            iterstack.pop_back();
            (*child)->children.erase((*child)->children.begin());
            child++;
            continue;
        }
        if ((*child)->children.front()->indexEnd != INF) {
            iterstack.push_back(child);
            child = IChildIterator(*child);
            continue;
        }
        std::shared_ptr<TNode> temp = (*child)->children.front();
        if (temp->suffixLink) temp->suffixLink = nullptr;
        (*child)->children.erase((*child)->children.begin());
    }

    OutputDebugString(L"tree dies\n");
}

void CTree::LoadString(std::string* newString)
{
    string = new std::string(*newString);
}

void CTree::CreateTree()
{
    for (int i = 0; i < string->size(); i++) {
        ExtendTree();
    }
}

std::shared_ptr<TNode> CTree::GetRoot()
{
    return root;
}

void CTree::AddSuffixLink(std::shared_ptr<TNode> node)
{
    if (lastAddedNode) lastAddedNode->suffixLink = node;
    lastAddedNode = node->shared_from_this();
}

bool CTree::WalkDown(std::shared_ptr<TNode> node)
{
    if (activeLength >= node->EdgeLength(position)) {
        activeEdge += node->EdgeLength(position);
        activeLength -= node->EdgeLength(position);
        activeNode = node;
        return true;
    }
    return false;
}

void CTree::ExtendTree()
{
    ++position;
    lastAddedNode = nullptr;
    remainder++;
    while (remainder > 0) {
        if (activeLength == 0) activeEdge = position;
        std::shared_ptr<TNode> selected = nullptr;
        for each (std::shared_ptr<TNode> child in activeNode->children) {
            if (string->at(child->indexStart) == GetActiveEdge()) {
                selected = child;
                break;
            }
        }
        if (!selected) {
            std::shared_ptr<TNode> newLeaf(new TNode(position, count++));
            activeNode->children.push_back(newLeaf);
            AddSuffixLink(activeNode);
        }
        else {
            if (WalkDown(selected)) continue;
            if (string->at(selected->indexStart + activeLength) == string->at(position)) {
                activeLength++;
                AddSuffixLink(activeNode);
                break;
            }
            //split
            if (selected->children.size() > 0) {
                long lastStart = selected->indexStart;
                selected->indexStart = selected->indexStart + activeLength;
                std::shared_ptr<TNode> newNode(new TNode(lastStart, count++));
                newNode->indexEnd = selected->indexStart;
                newNode->children.push_back(selected);
                std::shared_ptr<TNode> yetAnotherNewLeaf(new TNode(position, count++));
                newNode->children.push_back(yetAnotherNewLeaf);
                std::vector<std::shared_ptr<TNode>>::iterator iter;
                iter = activeNode->children.begin();
                while (true) {
                    if (*iter == selected) {
                        activeNode->children.insert(iter, newNode);
                        iter = activeNode->children.begin();
                        while (true) {
                            if (*iter == selected) {
                                activeNode->children.erase(iter);
                                break;
                            }
                            iter++;
                        }
                        break;
                    }
                    iter++;
                }
                AddSuffixLink(newNode);
            }
            else {
                selected->indexEnd = selected->indexStart + activeLength;
                std::shared_ptr<TNode> newLeaf(new TNode(selected->indexEnd, count++));
                selected->children.push_back(newLeaf);
                std::shared_ptr<TNode> yetAnotherNewLeaf(new TNode(position, count++));
                selected->children.push_back(yetAnotherNewLeaf);
                AddSuffixLink(selected);
            }
        }
        remainder--;
        if (activeNode == root && activeLength > 0) {
            activeLength--;
            activeEdge = position - remainder + 1;
        }
        else {
            if (activeNode->suffixLink) {
                activeNode = activeNode->suffixLink;
            }
            else {
                activeNode = root;
            }
        }
    }
}

char CTree::GetActiveEdge()
{
    return string->at(activeEdge);
}

内存泄漏:

  • 在ExtendTree()方法中创建每个新节点期间
  • 树构造函数
  • 在线

      

    iter = activeNode-&gt; children.begin();

我很感激任何一种提示如何解决这个问题。

1 个答案:

答案 0 :(得分:1)

调用LoadString时可能存在泄漏:

void CTree::LoadString(std::string* newString)
{
    string = new std::string(*newString);
}

此功能不会删除以前分配的string

创建shared_ptr对象的方法也很奇怪。这不一定会导致内存泄漏,但看起来很奇怪。例如,你这样做:

std::shared_ptr<TNode> newLeaf(new TNode(position, count++));

当你应该这样做时:

std::shared_ptr<TNode> newLeaf = std::make_shared<TNode>(position, count++)