哈希表和链表的 C++ 访问冲突
Posted
技术标签:
【中文标题】哈希表和链表的 C++ 访问冲突【英文标题】:C++ Access Violation With Hash Tables and Linked Lists 【发布时间】:2013-03-10 01:28:18 【问题描述】:所以我一直在尝试创建一个处理 1000 个链表的类,并最初声明指向它们的指针。
这是直接处理我的问题的代码:
struct node
char name[40];
char numb[12];
node * next;
;
class hashTable
public:
//Creates a table of 1000 pointers to linked-list nodes
node * table[1000];
//Functions
void addNode(char name[40], char numb[12])
node * temp; //Initializes temp node as pointer
temp = new node; //Points temp node to a new node
int hash = h(g(name)); //The hash of the key (name) used to check nodes
temp = table[hash]; //sets the temporary node to the first node of the list
while (temp->next != 0)
//...
就在 while 循环中,我收到错误“访问冲突读取位置 0xcccccd00” 我不确定为什么它无法访问表成员,除非可能是因为这些值尚未初始化或其他原因?
【问题讨论】:
可能是因为这些值没有被初始化或者什么的? 我会说这是未初始化内存的偏移量。由于 0xcccccccc 表示在 VC 调试模式下未初始化。 ***.com/questions/127386/… 站点注释:将表格大小更改为 997 或 1009。 您是否将表 [] 中的所有 1000 个指针都设为 NULL?好像你没有,因为你没有检查。等待一分钟不应该 temp = table[hash];成为表[hash]=temp; 你能在上面发布的代码中包含你的类构造函数吗?然后,将table
添加到初始值设定项列表中,特别是hashTable::hashTable() : table()
。另外,检查您刚刚从表之前收到的temp
,以使用temp->next
取消引用它。据您所知,之前没有任何东西,而且它不是一个有效的地址。
【参考方案1】:
您可能不会做两件事。首先确保您的哈希表已正确初始化为包含全空指针。其次,确保从哈希表中检索到的任何指针在解除引用之前是有效的:
第一期:
hashTable::hashTable() : table()
另外,你要确保这东西正确清理
hashTable::~hashTable()
for (size_t i=0;i<sizeof(table)/sizeof(table[0]); ++i)
node *temp = table[i];
while (temp)
node *victim = temp;
temp = temp->next;
delete victim;
第二期:
void addNode(const char *name, const char *numb)
int hash = h(g(name)); //The hash of the key (name) used to check nodes
node *temp = table[hash]; //sets the temporary node to the first node of the list
if (temp)
// preexisting entry. walk that list looking for matching key.
node **pp = &temp->next;
while (temp)
if (0 == strcmp(temp->name, name))
break;
pp = &temp->next;
temp = temp->next;
// link to last node if not found in list
if (!temp)
*pp = new node(name, numb);
else
// no prior entry. create a new one and store it at table[hash].
table[hash] = new node(name, numb);
注意:以上代码假设节点类实现为
struct node
char name[40];
char numb[12];
node * next;
node(const char* name_, const char *numb_)
: next()
strncpy(name, name_, sizeof(name)/sizeof(name[0])-1);
name[ sizeof(name)/sizeof(name[0])-1 ] = 0;
strncpy(numb, numb_, sizeof(numb)/sizeof(numb[0])-1);
numb[ sizeof(numb)/sizeof(numb[0])-1 ] = 0;
;
就个人而言,我会使用std::string
【讨论】:
这似乎比我的猜测更有可能。结果 temp = new node;在这种情况下没有任何意义。 非常感谢您的详细解答。现在开始有意义了。 :) 呃,最后一件事。使用代码初始化指向 NULL 的指针,当我多次使用相同的确切条目时,此“if (temp)”现在永远不会为假。 @KevSana 第一次时间槽被映射并且冲突列表存在时将是错误的。之后,添加的每个插槽中的初始节点始终是该插槽集合列表的第一个节点。这就是冲突列表的起点。顺便说一句,如果你也对集合列表进行排序,你可以显着加快速度,但这会改变你的哈希表的布局,需要一个数组指针和每个槽的列表大小。如果速度是最终目标,那么值得考虑。【参考方案2】:如果 hash 的值大于(或等于)1000,temp 将指向一个无效区域。
而且您正在泄漏由new node
分配的内存,因为您正在覆盖临时变量。
【讨论】:
以上是关于哈希表和链表的 C++ 访问冲突的主要内容,如果未能解决你的问题,请参考以下文章