我试图用动态数组编写一个哈希映射,该数组存储一组指向链表结构的指针。我一直在遇到一些奇怪的记忆问题。似乎我的数组中有指针不应该存在。
我收到一个错误,即使我应该从单个插入生成的索引是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
有什么想法吗?
答案 0 :(得分:1)
从您的代码中,我可以告诉您从堆中分配链接列表,这意味着您无法保证操作系统可以帮助您清除已分配的内存。
实际上, nullptr 意味着它只是指向地址NULL(零),你无法读取/写入它,因此指针是&#34; null&#34;。
有一种C语言解决方案比循环更好并且设置为 nullptr :在分配HashTable::buck
memset(buck,0,sizeof(buck));
此行将HashTable::buck
空格中的字节设置为零。