我正在为我的一个类使用Doubly Linked列表编写HashTable,但是当我运行valgrind时遇到错误。它说:条件跳跃或移动取决于未初始化的值。当我运行--track-origins = yes时,它说:
==11453== Conditional jump or move depends on uninitialised value(s)
==11453== at 0x402904: LinkedList<std::string>::itemExists(std::string const&) (LinkedList.h:89)
==11453== by 0x401FE6: HashSet<std::string>::find(std::string const&) (HashSet.h:85)
==11453== by 0x401E42: HashSet<std::string>::add(std::string const&) (HashSet.h:39)
==11453== by 0x4019D7: insert(std::string, std::basic_ifstream<char, std::char_traits<char> >&, std::basic_ofstream<char, std::char_traits<char> >&, std::string, HashSet<std::string>&) (main.cpp:64)
==11453== by 0x4015B1: main (main.cpp:34)
==11453== Uninitialised value was created by a heap allocation
==11453== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11453== by 0x4024D8: HashSet<std::string>::rehash() (HashSet.h:131)
==11453== by 0x401E69: HashSet<std::string>::add(std::string const&) (HashSet.h:45)
==11453== by 0x4019D7: insert(std::string, std::basic_ifstream<char, std::char_traits<char> >&, std::basic_ofstream<char, std::char_traits<char> >&, std::string, HashSet<std::string>&) (main.cpp:64)
==11453== by 0x4015B1: main (main.cpp:34)
所以我认为问题在于我的rehash功能,但我无法弄清楚它在哪里。你能帮助我吗?这是我的rehash功能:
void rehash()
{
int old_size = tableSize;
if (tableSize == itemsStored) {
tableSize = tableSize * 2 + 1;
}
else if (itemsStored <= tableSize/2) {
tableSize = tableSize / 2;
}
LinkedList<string>* newTable = new LinkedList<string>[tableSize]; -------> line 131
for (int i = 0; i < old_size; ++i)
{
int table_size = 0;
table_size = table[i].getSize();
if(table_size != 0) {
for (int j = 0; j < table_size; ++j) {
unsigned index = hashFunction(table[i].getItem(j)) % tableSize;
newTable[index].insert(newTable[index].getSize(), table->getItem(i));
}
}
}
LinkedList<string>* temp = table;
table = newTable;
delete [] temp;
}
这是Hash Set的构造函数:
HashSet()
{
int tableSize = 0;
table = new LinkedList<string>[tableSize];
}
这是LinkedList的构造函数:
LinkedList()
{
size = 0;
}
谢谢!
答案 0 :(得分:1)
我将在这里做一个幸运的猜测:你的LinkedList
包含一个head
指针,你的itemExists
函数会在检查size
字段是否为Node* node = head;
for (size_t i = 0; i < size; i++)
{
if (node->hash == ...)
...
node = node->next;
}
之前加载该指针大于零。
像
这样的东西size == 0
看起来无辜,因为如果helloWorld
指针没有被解除引用,但读取未初始化的指针本身就是UB。
答案 1 :(得分:0)
哦,我的,很难发现。如果不是@PaulGroke已经提出的建议,那么这里也存在一个潜在的问题:
HashSet()
{
/* */int/* */ tableSize = 0; // HERE!
table = new LinkedList<string>[tableSize];
}
从你的rehash
成员函数我猜你的哈希集类有一个名为tableSize
的成员。上面的构造函数有一个局部变量,其名称与 shadows 这个成员相同。因此,成员字段永远不会初始化,并且您具有未定义的行为。删除标记的int
应解决此问题。
通常,您应该使用初始化列表来编写构造函数:
HashSet()
: tableSize(0),
table(new LinkedList<string>[tableSize]); {
}
虽然我是否应该按照上面的说法对分配进行分析,这是值得商榷的,但是你通常不应该在代码中使用原始new
或new []
,更好std::shared_pointer
/ std::unique_pointer
或std::vector
。