C ++数组应该是空的

时间:2018-04-29 20:59:19

标签: c++ memory

我试图用动态数组编写一个哈希映射,该数组存储一组指向链表结构的指针。我一直在遇到一些奇怪的记忆问题。似乎我的数组中有指针不应该存在。

我收到一个错误,即使我应该从单个插入生成的索引是16,因为我遍历数组,有一些非零项:

start 
16 //(output of index from insert)
dumbtest //(get of nonexistent key)
0 // result of get of non-existent key
HashTable:
    0   0x0--
    0x0

    1   0x0--
    0x0

    2   0xeb-- //Why is this not 0x0?  
        0xeb

我最终收到了错误:Thread 1: EXC_BAD_ACCESS (code=1, address=0x80000002c)

来自字符串库中的这一行:

 _LIBCPP_INLINE_VISIBILITY
    bool __is_long() const _NOEXCEPT
        {return bool(__r_.first().__s.__size_ & __short_mask);}

我猜测这是将数组中的垃圾视为指针,然后尝试将随机字节转换为"键的字符串"属性。

这是类文件

#include "hashtable.hpp"
using namespace std;

HashTable::HashTable()
{
    this->length = 32;
    this->buck = new LinkedList *[32];
};


unsigned int HashTable::hash(string key)
{
    int hash = 7;
    for (int i = 0; i < key.length(); i++) {
        hash = hash*31 * key[i];
    }
    hash = hash % this->length;
    return std::abs(hash);
}

int HashTable::find(string key)
{
    int index = this->hash(key);
    LinkedList *curr = this->buck[index];
    while(curr != nullptr)
    {
        if(curr->key == key)
        {
//            std::cout << curr;
            int val = curr->value;
            return val;
        }

        curr = curr->next;
    }
    return 0;
}


void HashTable::output()
{
    cout << "\nHashTable:\n";
    for(int i = 0; i < this->length; i++)
    {
        LinkedList *curr = this->buck[i];
        cout << "\t";
        cout << i;
        cout << "\t";
        cout << curr;
        cout << "--\n\t";
        while (curr != nullptr){
            cout << "\t";
            cout << curr;
            cout << ":";
            cout << curr->key;
            cout << ",";
            cout << curr->value;
            cout << ",";
            cout << curr->next;
            curr = curr->next;
        }
        cout << this->buck[i];
        cout << "\n";
        cout << "\n";
    }
}

void HashTable::insert(string key, int value)
{
    unsigned int index = this->hash(key);
    cout << index;
    LinkedList *curr = this->buck[index];
    LinkedList *ins = new LinkedList{
        key,
        value,
        NULL,
    };
    if (curr == nullptr){
        this->buck[index] = ins;
    }
    else
    {
        while(curr->next != nullptr)
        {
            curr = curr->next;
        }

        curr->next = ins;
    }
}



void HashTable::rehash()
{
    this->length = 2 * this->length;
    LinkedList** old = this->buck;
    this->buck = new LinkedList* [this->length];
    for (int i=0; i < this->length; i++)
    {
        LinkedList* curr = old[i];
        while(curr != nullptr)
        {
            this->insert(curr->key, curr->value);
            curr = curr->next;
        }
    }
}

然后我的标题

#ifndef hashtable_hpp
#define hashtable_hpp

#include <stdio.h>
#include <string>
#include <iostream>


struct LinkedList
{
    std::string key;
    int value;
    LinkedList *next;
};


class HashTable
{
private:
    int length;
    LinkedList** buck;
    unsigned int hash(std::string key);
    void rehash();

public:
    HashTable();
    int find(std::string key);
    void insert(std::string key, int value);
    bool remove(std::string key);
    void output();

};
#endif /* hashtable_hpp */

这是运行它的主文件:

#include <stdio.h>
#include <string>
#include <iostream>
#include "hashtable/hashtable.hpp"

int main(int argc, const char * argv[])
{
    std::cout << "start\n";

    HashTable ht;
    ht.insert("test", 3);
//    ht.output();
    std::cout << "\ndumbtest\n";
    int dumbval = ht.find("testy");
    std::cout << dumbval;
    ht.output();

    std::cout << "\ntest\n";
    int val = ht.find("test");
    std::cout << val;

    std::cout << "\nend";
    return 0;
}

这是堆栈跟踪:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x80000002c)
  * frame #0: 0x00000001000021bd algStudy`std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<<<char, std::__1::char_traits<char>, std::__1::allocator<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) [inlined] std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__is_long(this="") const at string:1221
    frame #1: 0x00000001000021bd algStudy`std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<<<char, std::__1::char_traits<char>, std::__1::allocator<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) [inlined] std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__get_pointer(this="") const at string:1315
    frame #2: 0x00000001000021bd algStudy`std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<<<char, std::__1::char_traits<char>, std::__1::allocator<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) [inlined] std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::data(this="") const at string:1129
    frame #3: 0x00000001000021bd algStudy`std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<<<char, std::__1::char_traits<char>, std::__1::allocator<char> >(__os=0x00007fff9b480660, __str="") at ostream:1047
    frame #4: 0x0000000100002067 algStudy`HashTable::output(this=0x00007ffeefbff4c8) at hashtable.cpp:63
    frame #5: 0x00000001000014c5 algStudy`main(argc=1, argv=0x00007ffeefbff5e8) at main.cpp:23
    frame #6: 0x00007fff6388d015 libdyld.dylib`start + 1
    frame #7: 0x00007fff6388d015 libdyld.dylib`start + 1

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

从您的代码中,我可以告诉您从堆中分配链接列表,这意味着您无法保证操作系统可以帮助您清除已分配的内存。

实际上, nullptr 意味着它只是指向地址NULL(零),你无法读取/写入它,因此指针是&#34; null&#34;。

有一种C语言解决方案比循环更好并且设置为 nullptr :在分配HashTable::buck

之后添加此单行
memset(buck,0,sizeof(buck));

此行将HashTable::buck空格中的字节设置为零。