【问题标题】:memory leak in my hashtable c++我的哈希表 C++ 中的内存泄漏
【发布时间】:2013-11-17 04:21:18
【问题描述】:

我创建了一个哈希表类,并以这种方式编写了它的析构函数

HashMap::~HashMap()
{
    for (int i=0; i<cap; i++)
    {
        Node* ptr = Hashtable[i];
        while (ptr)
        {
            Node* delptr;
            delptr=ptr;
            ptr=ptr->next;
            delete delptr;
        }
    }
    delete [] Hashtable;
}

既然有析构函数,为什么还要一直泄漏内存?

这是我如何实现构造函数

HashMap::HashMap()
{
    Hashtable= new Node* [INITIAL_BUCKET_COUNT];
    sz=0;
    cap=INITIAL_BUCKET_COUNT;
    hashfunction=defaulthashfunction;
}

additem函数是:

void HashMap::add(const std::string& key, const std::string& value)
{
    int index = hashfunction(key)%cap;;
    Node* ptr=Hashtable[index];
    Node* newnode=new Node;
    if (contains(key)==false)
    {
        if (ptr == nullptr)
        {
            newnode->key=key;
            newnode->value=value;
            newnode->next=NULL;
            Hashtable[index]=newnode;
        }
        else
        {
            newnode->key=key;
            newnode->value=value;
            newnode->next=NULL;
            while(ptr->next != NULL)
            {
                ptr = ptr->next;
            }
            ptr->next=newnode;
         }}
    if (loadFactor() > 0.8)
    {
        int newcap = cap*2+1;
        Node** newhash = new Node* [newcap];
        rehash(newhash, Hashtable, cap, newcap);
        for (int i=0; i <cap; i++)
        {
            Node* ptr=Hashtable[i];
            while (ptr)
            {
                Node* delptr;
                delptr=ptr;
                ptr=ptr->next;
                delete delptr;
            }
        }
        delete [] Hashtable;
        Hashtable=newhash;
    }
}

这是我的 rehash 函数,唯一的错误总是这一行: Node* nnode = new Node; 如果我将此代码放在循环之外,则错误变为 20,这表明问题出在我的析构函数中。但在调整我的哈希表大小之前,它没有错误,我测试了几次。为什么rehash函数会一直泄漏内存?

void HashMap::rehash(Node** newhash, Node** oldhash, int oldcap, int newcap)
{
    for (int x=0; x<newcap; x++)
    {
        newhash[x]=NULL;
    }
    //Node* nnode = new Node;
    for (int i = 0; i<oldcap; i++)
    {
        Node* ptr=oldhash[i];
        while (ptr!=NULL)
        {

            int index = hashfunction(ptr->key)%newcap;
            Node* nptr=newhash[index];
            Node* nnode = new Node;
            if (nptr==NULL)
            {
                nnode->key=ptr->key;
                nnode->value=ptr->value;
                nnode->next=NULL;
                newhash[index]=nnode;
            }
            else
            {
                while (nptr->next != NULL)
                {
                    nptr=nptr->next;
                }
                nnode->key=ptr->key;
                nnode->value=ptr->value;
                nnode->next=NULL;
                nptr->next=nnode;
                }
            ptr=ptr->next;
         }
    }
}

-- 插入--

【问题讨论】:

  • 确定 HashMap::~HashMap() 真的被调用了吗?在相关的不,停止使用未初始化的数据评估。如果您不知道这些是什么,int a; if (a &lt; 10)... 就是一个例子。另一个:int *p; if (p != nullptr)... 这样做会调用未定义的行为。
  • 如果无法看到您的声明,就无法判断您是否进行了适当的清理。
  • 如何初始化数据?我需要调用~HashMap()吗???否则,为什么不被调用。

标签: c++ memory-leaks hashmap hashtable


【解决方案1】:

Valgrind 输出中没有任何内容表明存在内存泄漏。

==6949== LEAK SUMMARY:
==6949==    definitely lost: 0 bytes in 0 blocks
==6949==    indirectly lost: 0 bytes in 0 blocks

然而,Valgrind 告诉你你没有初始化一些数据:

==6949== Conditional jump or move depends on uninitialised value(s)
==6949==  Uninitialised value was created by a heap allocation
==6949==    at 0x402B774: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==6949==    by 0x804A75C: HashMap::HashMap() (HashMap.cpp:31)

==6949== Conditional jump or move depends on uninitialised value(s)
==6949==    at 0x402B774: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==6949==    by 0x804A75C: HashMap::HashMap() (HashMap.cpp:31)

==6949== Use of uninitialised value of size 4

具体来说,你的构造函数HashMap::HashMap() (HashMap.cpp:31),问题出在那儿,而不是你的析构函数。

最后,由于空指针访问,您的代码崩溃了。

==6949== Invalid read of size 4
==6949==    at 0x40EAD76: std::string::assign(std::string const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.18)
==6949==    by 0x804A51A: main (main.cpp:16)
==6949==  Address 0x0 is not stack'd, malloc'd or (recently) free'd

你应该看看 main.cpp 的第 16 行,看看它在做什么,但是在你修复那些未初始化的值之前,所有的赌注都没有。

【讨论】:

  • 是的!如何初始化值? ==6949== at 0x804B004: HashMap::size() const (HashMap.cpp:274) ==6949== by 0x804AF87: HashMap::loadFactor() const (HashMap.cpp:293) 这些都是需要的函数无参数,有返回值。
  • 问题在于你的构造函数。 Valgrind 说Uninitialised value was created ... HashMap::HashMap()。根据 ValGrind,HashMap.cpp 线 31
  • 这意味着您的一个或多个成员变量没有被初始化。您的 HashMapNode 课程之一。
  • 例如 - 您没有将任何 m_hashTable[] 值设置为 NULL 或在 [INITIAL_BUCKET_COUNT] 之后添加 ()
  • 你的意思是我初始化了一个Hashtable,但它是一个空的bucket数组?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-15
  • 2020-10-09
  • 1970-01-01
  • 1970-01-01
  • 2019-05-21
  • 1970-01-01
  • 2012-12-13
相关资源
最近更新 更多