如何修复访问冲突读取位置错误

How to fix Access Violation Reading location error?

本文关键字:位置 错误 读取 访问冲突 何修复      更新时间:2023-10-16

我目前正在开发一个使用哈希表的程序。我已经处理了我自己的哈希表类,该程序可以工作,但在完成了涉及哈希表的工作后崩溃了。我得到的错误是访问违规读取位置错误。我花了几个小时仔细检查我的代码,仍然找不到我做错了什么,也找不到程序崩溃的原因。以下是我的问题类:

哈希表.h:

#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <string>
#include "LinkedList.h"
#include <iostream>
using namespace std;
class hashTable
{
    public:
        hashTable();
        virtual ~hashTable();
        void insertNode(string nodeData);
        bool removeNode(string nodeKey);
          Node * checkForDuplicate( string nodeData );
    private:
        LinkedList * tableArray;
        int length;
        int hash(string stateKey);
};
#endif // HASHTABLE_H

Hashtable.cpp:

#include "hashTable.h"

hashTable::hashTable()
{
   length = 181667;
   tableArray = new LinkedList[length];
}
int hashTable::hash(string stateKey) {
    int multiplier = 1;
    int total = 0;
    int l = stateKey.length();
    for(int i = l - 1; i > -1; --i) {
        int temp;
        temp = (stateKey[i] - '0') * multiplier;
        total += temp;
        multiplier = multiplier * 10;
    }
    return(total) % length;
}
void hashTable::insertNode(string stateData) {
    Node * newNode;
    newNode = new Node;
    newNode->data = stateData;
    int index = hash(newNode -> data);
    tableArray[index].insertNode(newNode);
    delete newNode;
}
bool hashTable::removeNode(string nodeKey) {
    int index = hash(nodeKey);
    return tableArray[index].removeNode(nodeKey);
}
Node * hashTable::checkForDuplicate( string nodeData )
{
    int index = hash( nodeData );
    return tableArray[ index ].getNode(nodeData);   
}

hashTable::~hashTable()
{
    delete [] tableArray;
    //dtor
}

LinkedList.h:

#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include<string>
#include<iostream>
using namespace std;
struct Node {
    string data;
    Node *next;
};
class LinkedList
{
    public:
        LinkedList();
        void insertNode(Node * newNode);
        bool removeNode(string stateData);
        Node * getNode(string stateData);
        int getLength();
        virtual ~LinkedList();
    private:
        Node * top;
        int length;
};
#endif // LINKEDLIST_H

LinkedList.cpp:

#include "LinkedList.h"
LinkedList::LinkedList()
{
    top = new Node;
    top->next = NULL;
    length = 0;
}
void LinkedList :: insertNode(Node * newNode) {
    Node * a = top;
    Node * b = top;
    while(b) {
        a = b;
        b = a -> next;
        if (a== NULL) { break; }
    }
    a -> next = newNode;
    newNode -> next = NULL;
    length++;
 }

bool LinkedList :: removeNode(string stateData) {
    if(!top -> next){
        return false;
    }
    Node * a = top;
    Node * b = top;
    while(b) {
        if(b->data == stateData) {
            a->next = b->next;
            delete b;
            length--;
            return true;
        }
        a = b;
        b = a ->next;
    }
    return false;
}
Node * LinkedList :: getNode(string stateData) {
    if(top == NULL) { return NULL ;}
    Node * current = top;
    while (current->next != NULL) {
        if((current->data == stateData)) {
            return current;
        }
        current = current -> next;
    }
    return NULL;
}
int LinkedList :: getLength() {
    return length;
}
LinkedList::~LinkedList()
{
    Node * a = top;
    Node * b = top;
    while (b) {
        a = b;
        b = a->next;
        if(b) delete a;
    }
}

您的hashTable::insertNode()方法是分配一个新的Node对象,然后将其传递给LinkedList::insertNode()获得该对象的所有权,但随后delete将其移除,从而使LinkedList具有指向无效内存的悬空指针。对该节点的任何访问都将导致未定义的行为。在LinkedList取得新节点的所有权后,不要delete

如果LinkedList::insertNode()采用string而不是Node*指针作为输入,则会更好。让LinkedList在内部分配新节点。

此外,您的LinkedList()实现总体上还有一些其他小问题(比如不遵循"三条规则",以及不使用双链表进行更有效的插入和删除)。

试试类似的东西:

哈希表.h:

#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <string>
#include "LinkedList.h"
class hashTable
{
public:
    hashTable();
    hashTable(const hashTable &src);
    ~hashTable();
    void insertNode(const std::string &nodeData);
    bool removeNode(const std::string &nodeData);
    bool checkForDuplicate(const std::string &nodeData);
    hashTable& operator=(const hashTable &rhs);
private:
    std::vector<LinkedList> tableArray;
    int length;
    int hash(const std::string &nodeData);
};
#endif // HASHTABLE_H

Hashtable.cpp:

#include "hashTable.h"
hashTable::hashTable()
   : length(181667), tableArray(new LinkedList[length])
{
}
hashTable::hashTable(const hashTable &src)
    : length(src.length), tableArray(new LinkedList[length])
{
    for (int i = 0; i < length; ++i)
        tableArray[i] = src.tableArray[i];
}
hashTable::~hashTable()
{
    delete[] tableArray;
}
hashTable& hashTable::operator=(const hashTable &rhs)
{
    hashTable tmp(rhs);
    std::swap(tableArray, tmp.tableArray);
    std::swap(length, tmp.length);
    return *this;
}
int hashTable::hash(const std::string &nodeData)
{
    int multiplier = 1;
    int total = 0;
    int l = nodeData.length();
    for(int i = l - 1; i > -1; --i)
    {
        int temp = (nodeData[i] - '0') * multiplier;
        total += temp;
        multiplier *= 10;
    }
    return total % length;
}
void hashTable::insertNode(const std::string &nodeData)
{
    int index = hash(nodeData);
    tableArray[index].insertNode(nodeData);
}
bool hashTable::removeNode(const std::string &nodeData)
{
    int index = hash(nodeData);
    return tableArray[index].removeNode(nodeData);
}
bool hashTable::checkForDuplicate(const std::string &nodeData)
{
    int index = hash(nodeData);
    return (tableArray[index].getNode(nodeData) != NULL);
}

LinkedList.h:

#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <string>
struct Node
{
    std::string data;
    Node *previous;
    Node *next;
};
class LinkedList
{
public:
    LinkedList();
    LinkedList(const LinkedList &src);
    ~LinkedList();
    void insertNode(const std::string &nodeData);
    bool removeNode(const std::string &nodeData);
    Node* getNode(const std::string &nodeData);
    int getLength();
    LinkedList& operator=(const LinkedList &rhs);
private:
    Node *head;
    Node *tail;
    int length;
};
#endif // LINKEDLIST_H

LinkedList.cpp:

#include "LinkedList.h"
#inclue <algorithm>
LinkedList::LinkedList()
    : head(NULL), tail(NULL), length(0)
{
}
LinkedList::LinkedList(const LinkedList &src)
    : head(NULL), tail(NULL), length(0)
{
    Node *current = src.top;
    while (current != NULL)
    {
        insertNode(current->data);
        current = current->next;
    }
}
LinkedList::~LinkedList()
{
    Node *current = top;
    while (current != NULL)
    {
        Node *next = current->next;
        delete current;
        current = next;
    }
}
LinkedList& LinkedList::operator=(const LinkedList &rhs)
{
    LinkedList tmp;
    Node *current = rhs.top;
    while (current != NULL)
    {
        tmp.insertNode(current->data);
        current = current->next;
    }
    std::swap(top, tmp.top);
    std::swap(bottom, tmp.bottom);
    std::swap(length, tmp.length);
    return *this;
}
void LinkedList::insertNode(const string &nodeData)
{
    Node *newNode = new Node;    
    newNode->data = nodeData;
    newNode->previous = NULL;
    newNode->next = NULL;
    if (top == NULL) top = newNode;
    if (bottom != NULL)
    {
        newNode->previous = bottom;
        bottom->next = newNode;
    }
    bottom = newNode;
    length++;
 }
bool LinkedList::removeNode(const string &nodeData)
{
    Node* node = getNode(nodeData);
    if (node != NULL)
    {
        if (node->next != NULL)
            node->next->previous = node->previous;
        if (node->previous != NULL)
            node->previous->next = node->next;
        if (top == node)
            top = node->next;
        if (bottom == node)
            bottom = node->previous;
        delete node;
        length--;
        return true;
    }
    return false;
}
Node* LinkedList::getNode(const string &nodeData)
{
    Node *current = top;
    while (current != NULL)
    {
        if (current->data == nodeData)
            return current;
        current = current->next;
    }
    return NULL;
}
int LinkedList::getLength()
{
    return length;
}

也就是说,您可以使用std::list来完全摆脱LinkedList,并使用std::vector:来简化hashTable的内存管理

哈希表.h:

#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <string>
#include <list>
#include <vector>
class hashTable
{
public:
    hashTable();
    void insertNode(const std::string &nodeData);
    bool removeNode(const std::string &nodeData);
    bool checkForDuplicate(const std::string &nodeData);
private:
    std::vector< std::list<std::string> > tableArray;
    int hash(const std::string &stateKey);
};
#endif // HASHTABLE_H

Hashtable.cpp:

#include "hashTable.h"
#include <algorithm>
hashTable::hashTable()
   : tableArray(181667)
{
}
int hashTable::hash(const std::string &nodeData)
{
    int multiplier = 1;
    int total = 0;
    int l = nodeData.length();
    for(int i = l - 1; i > -1; --i)
    {
        int temp = (nodeData[i] - '0') * multiplier;
        total += temp;
        multiplier *= 10;
    }
    return total % length;
}
void hashTable::insertNode(const std::string &nodeData)
{
    int index = hash(nodeData);
    tableArray[index].push_back(nodeData);
}
bool hashTable::removeNode(const string &nodeData)
{
    int index = hash(nodeData);
    std::list<std::string>::iterator iter = std::find(tableArray[index].begin(), tableArray[index].end(), nodeData);
    if (iter != tableArray[index].end())
    {
        tableArray[index].erase(iter);
        return true;
    }
    return false;
}
bool hashTable::checkForDuplicate(const std::string &nodeData)
{
    int index = hash(nodeData);
    std::list<std::string>::iterator iter = std::find(tableArray[index].begin(), tableArray[index].end(), nodeData);
    return (iter != tableArray[index].end());
}