【问题标题】:HashTable Keeps producing segFault. How to properly delete using destructor?HashTable 不断产生 segFault。如何使用析构函数正确删除?
【发布时间】:2018-11-06 10:39:43
【问题描述】:

我有一个 HashTable 类。这样做的目的是练习如何生成哈希表。我目前的问题是析构函数。我应该在控制台上看到,这个:

但我看到的是:

我运行了gdb ./app,它给了我这个:

#include <iostream>
#include "HashTable.h"

using namespace std;

int main(){
 HashTable table;
 table.initTable();
 table.addNode("Software");
 table.addNode("Engineering");
 table.addNode("Art");
 table.addNode("Programming");
 table.addNode("Miscellanous");
 table.displayByIndex();
 return 0;
}

哈希表头:

#ifndef _HASHTABLE_H_
#define _HASHTABLE_H_

#include <iostream>
#include "Hash.h"

class HashTable{
private:
    static const int TABLESIZE = 5;
    Hash* head;
public:
    HashTable();
    ~HashTable();

    void initTable();
    int hashKey(char*);
    int quadProbing(int,int);
    int hashKeyWithProbing(char*);
    bool isEmpty();
    void addNode(char*);
    void displayByIndex();
    void searchByKey(char*);

};#endif

这是我的哈希表 CPP,我包含了构造函数/析构函数和初始化函数。由于我不使用“新”关键字,因此不包括其他功能。如果需要,我会包含它[希望使这个线程变小]

#include "HashTable.h"
#include <cstring>

HashTable::HashTable(){
  head = new Hash[TABLESIZE];
}
HashTable::~HashTable(){
  Hash* destList = NULL;
   for(int i = 0; i< TABLESIZE; i++){
     destList = &head[i];
     while(destList != NULL){
        head = head->getNext();
        delete destList;
        destList = head;
     }
   }
   head = NULL;
   delete [] head;
}
void HashTable::initTable(){
  for(int i = 0; i < TABLESIZE; i++){
    Hash *traverseHeadArray = &head[i];
    traverseHeadArray->setKey("EMPTY");
    traverseHeadArray->setNext(NULL);
    traverseHeadArray = NULL;
  }
} 

int HashTable::hashKey(char *tempKey){
 //Find the asc value for the string
//add them together
//modules by the total table size
//then return the index (remainder using modules)
//Index is were that key will be stored
 int index = 0;
 for(int i = 0; i < strlen(tempKey); i++){
    index += tempKey[i];
 }
  return index % TABLESIZE;
 }//DONE
int HashTable::quadProbing(int index, int counter){
  return (index + counter*counter) % TABLESIZE;
}//DONE
int HashTable::hashKeyWithProbing(char* key){
 int index = hashKey(key);
 int count = 1;

 while(head[index].getKey() != key && head[index].getKey() != "EMPTY"){
    index = quadProbing(index, count);
    count++;
 }
 return index;
}//DONE

void HashTable::addNode(char* tempValue){
 Hash* newNode = new Hash;
 newNode->setKey(tempValue);
 newNode->setNext(NULL);
 int index = hashKey(tempValue);
 int counter = 1;

 while(head[index].getKey() != tempValue && head[index].getKey() !="EMPTY")
  {
    index = quadProbing(index, counter);
    counter++;
  }

  Hash* traverse = &head[index];
 if(isEmpty() || traverse->getKey() == "EMPTY"){
    traverse->setKey(newNode->getKey());
    traverse->setNext(newNode->getNext());
 }else{
    while(traverse->getNext() != NULL)
        traverse = traverse->getNext();
    traverse->setNext(newNode);
 }
 traverse = NULL;  
 delete newNode;
}
void HashTable::displayByIndex(){
 for(int i = 0; i < TABLESIZE; i++){
    Hash *traverse = &head[i];
    std::cout << "----------------------------------------" << std::endl;
    std::cout << "INDEX: " << i << std::endl; 
    while(traverse != NULL){
        std::cout << "Key: " << traverse->getKey() << std::endl;
        traverse = traverse->getNext();
    }
    std::cout << "----------------------------------------" << std::endl;
    traverse = NULL;
  }
 }
 bool HashTable::isEmpty(){
  return (head == NULL);
 }
 void HashTable::searchByKey(char* key){
   int index = hashKeyWithProbing(key);

   if(isEmpty())
    std::cout << "Empty Bucket\n";
   else{
    Hash* traverse = &head[index];
    while(traverse != NULL && traverse->getKey() != "EMPTY"){
        std::cout << "TOPIC KEY: " << traverse->getKey() << std::endl;
        traverse = traverse->getNext();
    }
     traverse = NULL;
   }
  }

这是我的 Hash Class 头文件和 CPP 文件:

#ifndef _HASH_H_
#define _HASH_H_

class Hash{
 private:
    char* key;
    Hash* next;

 public:
    Hash();
    ~Hash();

    void setKey(char*);
    void setNext(Hash* const);
    char* getKey();
    Hash* getNext();

  };#endif



#include "Hash.h"
#include <iostream>

Hash::Hash(){
 key = NULL;
 next = NULL;
}
Hash::~Hash(){
// TODO Destructor
}

void Hash::setKey(char* tempKey){
 this->key = tempKey;
}
void Hash::setNext(Hash* const tempNext){
 this->next = tempNext;
}
char* Hash::getKey(){
 return key;
}
Hash* Hash::getNext(){
  return next;
}

【问题讨论】:

  • 请将您的代码作为文本粘贴到问题中。阅读有关如何创建minimal reproducible example 的信息。
  • @RetiredNinja 道歉,我虽然更快,但后来我意识到每个人都更容易复制和粘贴代码。感谢您的提醒!
  • 你能提供你的测试、输出和想要的输出吗
  • @DennisVash 我已经包含 main.cpp ,我只是想使用链表将键添加到每个索引中。文件编译,但我在 gdb 和 segfault 上得到一个无效指针。我只想输出特定索引中的每个列表。
  • 在空指针上调用delete[] 本质上是一个空操作。您确定文章没有先对delete 说,然后然后 将指针设置为空吗? (尽管只有在之后仍然可以访问指针时才需要这样做)

标签: c++ hashtable


【解决方案1】:

在您的代码中,您只分配了 getNext() 节点, 所以你应该只删除它们,(你试图删除根本没有分配的&amp;head[i])。 双重释放某些节点仍然存在异常,您应该调试并按照堆栈进行计算。

HashTable::~HashTable(){
    for(int i = 0; i< TABLE_SIZE; i++){
        Hash* node = head[i].getNext();
        while(node != nullptr){
            Hash* temp = nullptr;
            if (node -> getNext()) {
                temp = node->getNext();
            }
            delete node;
            node= temp;
        }
    }
    delete[] head;
}

输出:

----------------------------------------
INDEX: 0
Key: Art
----------------------------------------
----------------------------------------
INDEX: 1
Key: Engineering
----------------------------------------
----------------------------------------
INDEX: 2
Key: Miscellanous
----------------------------------------
----------------------------------------
INDEX: 3
Key: Software
----------------------------------------
----------------------------------------
INDEX: 4
Key: Programming
----------------------------------------
double free or corruption (fasttop)

Process finished with exit code 134 (interrupted by signal 6: SIGABRT)

【讨论】:

  • 所以我注意到 if(!head-&gt;getNext()){break;} 行,我已将它添加到我的源代码中,并且我设法让它编译和运行。但是,当我尝试将更多键添加到这些索引中时,我仍然遇到段错误。段错误仍然是同一个。我已经包括了上面的所有内容。
  • 很抱歉,我仍然遇到段错误。即使将其更改为if(!head){break;}
  • @JonathanVazquez 我建议重新检查addNode 方法。
  • 所以在我的 addNode 类中,如果我决定从 main 中添加另一个 table.addNode("Miscellanous);,我无法将其输出。但是,我决定从 addNode 函数中删除 delete newNode; 命令。现在我让它输出必要的信息,但由于newNode 未被分配,仍然存在段错误。
猜你喜欢
  • 2012-09-23
  • 2017-03-21
  • 2017-04-06
  • 2012-05-08
  • 2020-02-29
  • 2013-09-30
  • 1970-01-01
  • 2012-03-13
  • 1970-01-01
相关资源
最近更新 更多