如何在c ++中编写正确的Hash Table析构函数

时间:2013-11-17 23:43:03

标签: c++ memory-leaks hashmap hashtable destructor

我正在写一个c ++ Hashtable

这是我的析构函数:

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

我的添加功能:

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;
         }}}

但我一直在收到内存泄漏错误

==13676== 
==13676== HEAP SUMMARY:
==13676==     in use at exit: 12 bytes in 1 blocks
==13676==   total heap usage: 42 allocs, 41 frees, 669 bytes allocated
==13676== 
==13676== 12 bytes in 1 blocks are definitely lost in loss record 1 of 1
==13676==    at 0x402BE94: operator new(unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==13676==    by 0x804BF8D: HashMap::add(std::string const&, std::string const&) (HashMap.cpp:112)
==13676==    by 0x804AFD2: main (main.cpp:18)
==13676== 
==13676== LEAK SUMMARY:
==13676==    definitely lost: 12 bytes in 1 blocks
==13676==    indirectly lost: 0 bytes in 0 blocks
==13676==      possibly lost: 0 bytes in 0 blocks
==13676==    still reachable: 0 bytes in 0 blocks
==13676==         suppressed: 0 bytes in 0 blocks
==13676== 
==13676== For counts of detected and suppressed errors, rerun with: -v
==13676== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

它表示的行是Node * newnode = new Node;因为我在这里使用“new”,所以需要释放这个newnode,但是析构函数只在Hashtable中释放内容。如果我不使用“newnode”,我将有空指针访问错误,因为nullptr无法访问Node(Node是一个结构有键和值),我只能让指针指向“newnode”。但是,添加额外的“删除newnode”会让我收到20多个错误。我真的需要你的帮助!

如果我写这个,我仍然会收到错误

if (contains(key)==false)
{
    if (ptr == nullptr)
    {
        Node* newnode=new Node;
        newnode->key=key;
        newnode->value=value;
        newnode->next=NULL;
        Hashtable[index]=newnode;
    }
    else
    {
        Node* newnode=new Node;
        newnode->key=key;
        newnode->value=value;
        newnode->next=NULL;

        while(ptr->next != NULL)
        {
            ptr = ptr->next;
        }
        ptr->next=newnode;
     }}

3 个答案:

答案 0 :(得分:2)

问题是你这样做:

Node* newnode=new Node;
if (contains(key)==false)
    // ... store it
/*
else
    leak it
*/

您需要做的是在新的条件之前执行条件。

if(contains(key) == true) {
     // use the existing entry.
     ...
     return;
}
else {
    Node* newnode=new Node;
    // ... rest of your code for inserting a new entry here.
}

----编辑----

ValGrind告诉你的是你的代码在HashMap.cpp第112行分配了一个指针,但是它从未存储过地址 - 当有人用一个“包含”的键调用add函数时,代码就会发生这种情况(关键)“不返回虚假。您不存储指针,因此您分配的节点已分配,但您的代码未跟踪它 - &gt;这是泄密。

答案 1 :(得分:1)

这一行

Node* newnode=new Node; 

创建一个本地newnode指针,该指针在add函数退出后将超出范围。这将泄漏由new分配的内存。

答案 2 :(得分:0)

只需声明newnode,然后在if语句之后分配新节点。您的代码现在的方式是newnode可以被分配,if语句出错并且newnode保留在内存中从未使用过。