简体   繁体   English

C++ 自定义哈希表的使用给出了 SegFault

[英]C++ Custom HashTable usage gives SegFault

I had to implement a Linked HashTable for a project.我必须为一个项目实现一个 Linked HashTable。 Now I have to come up with an excercise and a solution to it using my hashtable.现在我必须想出一个练习和一个使用我的哈希表的解决方案。 Everything works just fine, except I get random Segfault errors.一切正常,除了我得到随机的 Segfault 错误。

By Random I mean: It is the same line of code that causes it, but always at different times, calls.随机我的意思是:它是导致它的同一行代码,但总是在不同的时间,调用。 I tested my code in Atom, Codeblocks and in Visual Studio Code.我在 Atom、Codeblocks 和 Visual Studio Code 中测试了我的代码。 Both Atom and CB threw SegFault error, but VS Code ran it just fine without a problem. Atom 和 CB 都抛出了 SegFault 错误,但 VS Code 运行得很好,没有问题。

NOTE: THIS IS NOT THE FULL/REAL CODE.注意:这不是完整/真实的代码。 It's part of a header file that is included in the main.cpp file which is then compiled and ran.它是 header 文件的一部分,该文件包含在 main.cpp 文件中,然后编译并运行该文件。 The Code:编码:

#include <iostream>
#include <typeinfo>
#include <string>

using namespace std;

//List:
template<class T>
struct Node
{
  string data;
  Node *next;
};

class List
{
  private:
    Node *head, *tail;
    int length;
    friend class HashTable;
  public:
    List();
    List(const List &L);
    //~List() {delete this;};
    List& operator =(List L);
    int find(string);
    void insert(string value);
    void remove_head();
    void remove_poz(int);
    void remove_tail();
    void clear();
    void display();
};

List::List()
{
   head = NULL;
   tail = NULL;
   length = 0;
}

template<>
string List<string>::findByIndex(int ind)
{
    int i = 0;
    Node<string>* temp = new Node<string>;
    temp = head;
    while (temp != NULL)
    {
        i++;
        if (i == ind) return temp->data;
        temp = temp->next;
    }
    delete temp;
    return "-1";
}

template<class T>
void List<T>::remove_head()
{
  Node<T>* temp = new Node<T>;
  temp = head;
  head = head->next;
  delete temp;
  length--;
}

template<class T>
void List<T>::remove_pos(int pos)
{
  int i;
  Node<T>* curr = new Node<T>;
  Node<T>* prev = new Node<T>;
  curr = head;
  for (i = 1; i < pos; ++i)
  {
      prev = curr;
      curr = curr->next;
  }
  if (curr)
  {
    prev->next = curr->next;
    length--;
  }
  else cout << "Error" << endl;
}

template<class T>
void List<T>::remove_tail()
{
  Node<T>* curr = new Node<T>;
  Node<T>* prev = new Node<T>;
  curr = head;
  while (curr->next != NULL)
  {
      prev = curr;
      curr = curr->next;
  }
  tail = prev;
  prev->next = NULL;
  delete curr;
  length--;
}

//HashTable:
class HashTable
{
  private:
    List *table;
    float load, stored;
    int slots;
    friend class List;
  public:
    HashTable();
    HashTable(int);
    ~HashTable();
    int hashFunc(string key);
    int findTable(string);
    int findList(string);
    HashTable& operator =(const HashTable&);
    void resize();    //I need this one
    void insert(string);
    void remove(string);
    void clear(int);
    void clear();
    void display();
};

HashTable::HashTable()
{
  stored = 0;
  load = 0.00;
  slots = 15;
  table = new List[slots];
}

int HashTable::hashFunc(string key)
{
  int g, h = 0;
    unsigned int i;
    for (i = 0; i < key.size(); ++i)
    {
        h = (h << 4) + (int)(key[i]);
        g = h & 0xF0000000L;
        if (g != 0)
        {
            h = h ^ (g >> 24);
        }
        h = h & ~g;
    }
    return h % slots;
}

template<class T>
void HashTable<T>::remove(T value)
{
  int ind = hashFunc(value);
  int findInd = table[ind].findByValue(value);


  if (findInd == 0)
      table[ind].remove_head();

  else if (findInd < table[ind].length)
      table[ind].remove_pos(findInd);

  else table[ind].remove_tail();

  if (table[ind].isEmpty()) occupied--;
  stored--;
  load = stored / slots;
}

The function that would cause the segfault: (This would be called over and over again in a loop till I don't have more elements in my table)会导致段错误的 function :(这将在循环中一遍又一遍地调用,直到我的表中没有更多元素)

string reakcio(HashTable<string>& HT, int tarolok)
{
    const int anyagszam = rand() % 4 + 2; //Min 2, Max 5 anyag hasznalodik
    int i = 0, j;
    string anyagok[5];
    string eredmeny;

    for(j = 0; j < tarolok && i < anyagszam; ++j) //elemek kivetele
    {
        while(!HT.table[j].isEmpty())
        {
            anyagok[i++] = HT.table[j].findByIndex(1); //This line right here is the culprit :(
            HT.remove(anyagok[i-1]);
        }
    }

    const int siker = rand() % 4 + 0; //75% esely a sikerre
    if (siker)
    {
        eredmeny = anyagok[0];
        for(i = 1; i < anyagszam; ++i)
            eredmeny += " + " + anyagok[i];
    }
    else
        eredmeny = "Sikertelen reakcio";
    return eredmeny;
}

(Note: only the functions that might be needed are shown here) (注意:这里只显示可能需要的功能)

Every element of my hashtable, or of my lists is a 10 character long random string value.我的哈希表或列表中的每个元素都是一个 10 个字符长的随机字符串值。 srand(time(NULL)) is used before the function call in main.cpp srand(time(NULL)) 在 main.cpp 中的 function 调用之前使用

Any help or advice would be much appreciated, as I'm stuck at this and I really need to move on to the next portion of my exercise, but I can't without this.任何帮助或建议将不胜感激,因为我坚持这一点,我真的需要继续进行下一部分练习,但我不能没有这个。

The main.cpp file: main.cpp 文件:

#include <iostream>
//#include "LinkedHash.h"
#include "functions.cpp"

int main()
{
  HashTable<string> Anyagok;
  int tarolok;

  tarol(Anyagok); //Stores the data from file, no problem here, functions.cpp
  tarolok = Anyagok.getSlots();

  srand(time(NULL));
  int i = 1;
  while (Anyagok.getStored() > 5 )
    cout<<reakcio(Anyagok, tarolok)<<" "<<i++<<endl;

  return 0;
}

The LinkedHash.h contains the hashtable and the list, the functions.cpp contains the problematic function. LinkedHash.h 包含哈希表和列表,functions.cpp 包含有问题的 function。

EDIT: By suggestion I changed out the编辑:根据建议我改变了

Node<string>* temp = new Node<string>;
temp = head;

part to部分到

Node<string>* temp = head;

Also removed the delete line.还删除了删除行。 But my problem is still the same:/但我的问题还是一样:/

Everything works just fine, except I get random Segfault errors一切正常,除了我得到随机的 Segfault 错误

Then nothing works at all.然后根本没有任何作用。

A first review show little care to the cornercases in the list class.第一次审查显示对 class 列表中的角落案例很少关注。 You need to define a correct behavior for您需要为

  • operation on empty lists对空列表的操作
  • operation on first and last element对第一个和最后一个元素的操作
  • key not found during search搜索期间未找到密钥

Notable errors found:发现明显错误:

  • remove_head, remove_tail will segfault on empty list. remove_head、remove_tail 将在空列表中出现段错误。 head is NULL.头是 NULL。 head->next is invalid memory access. head->next 无效 memory 访问。 Similar errors are all over the implementation.类似的错误遍布整个实现。
  • HashTable<T>::remove(T value) will always remove something. HashTable<T>::remove(T value)总是会删除一些东西。 Even if the value argument is not in the hashtable.即使 value 参数不在哈希表中。 This is deeply flawed这是严重缺陷
  • findByIndex returning "-1" make no sense. findByIndex 返回“-1”没有意义。 "-1" is a valid input. “-1”是一个有效的输入。
  • Node<T>* temp = new Node<T>;temp = head; . . You just leaked memory.你刚刚泄露了 memory。 You need a pointer to manipulate node addresses .您需要一个指针操作节点地址 You should not instantiate Nodes to get a pointer.您不应该实例化节点来获取指针。 This is not an issue (ie not noticeable) for a small projet, but unacceptable for a real implementation.这对于小型项目来说不是问题(即不明显),但对于实际实施来说是不可接受的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM