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

时间:2016-05-03 23:28:09

标签: c++ memory-leaks hashtable

我目前正在开发一个使用哈希表的程序。我已经在我自己的Hash表类上工作,程序可以运行但在它已经完成涉及哈希表的工作后崩溃了。我得到的错误是访问冲突读取位置错误。我花了几个小时查看我的代码,但仍然无法找到我做错的事情或程序崩溃的原因。以下是我的问题类:

Hashtable.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;
    }

}

1 个答案:

答案 0 :(得分:2)

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

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

此外,您的LinkedList实施通常存在一些其他小问题(例如,不遵循Rule of Three,并且不使用双链表进行更有效的插入和删除)。

尝试更像这样的东西:

Hashtable.h:

LinkedList()

Hashtable.cpp:

#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

LinkedList.h:

#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.cpp:

#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

话虽如此,您可以使用#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; } 完全删除LinkedList,并使用std::list简化hashTable的内存管理:

Hashtable.h:

std::vector

Hashtable.cpp:

#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