【问题标题】:Linked List C++ Seg fault链表 C++ Seg 错误
【发布时间】:2013-01-29 06:10:36
【问题描述】:

我正在尝试从头开始制作一个简单的链表,供另一个类使用。 错误似乎是有时 Head 未设置为 NULL。 我有时会说,它不会一直出现故障。它没有段错误的时间,它转到 else 语句。注意我只添加了 1 个字符串。也许你们能发现我没看到的东西,干杯!

LinkedList.h:

#include <string>
#include "Link.h"

using namespace std;

class LinkedList {
  Link *head;

public:
  LinkedList();
  void addFront(string key);
  void printList();
  //void addBack(string *);     

};

LinkedList.cpp:

#include <cstring>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include "LinkedList.h"

using namespace std;

LinkedList::LinkedList() {
   head = NULL;
}

void LinkedList::addFront(string key) {
  //creates the new list segment                                                
  Link *l = new Link(key);

  cout << "Made new Link " << key << endl;
  // if the list is empty                                                 
  if (head == NULL){
    cout << "Going to set Head " << key << endl;
    head = l;
    cout << "Set Head to new link " << key << endl;
 }                                            
  else {             
     cout << "Else statement " << key << endl;                  
    l->setNext(head);

    head = l;
  }

}

void LinkedList::printList() {
 //Check if list is empty
  if(head == NULL)
   cout << "NULL" << endl;
  else {
   Link *l = head; 

   for(;l != NULL; l=l->getNext())
     cout << l->getValue() << endl;
  }


}

// void LinkedList::addBack(string *f) {
//   Link *l = new Link(f);

// }

链接.h

#include <cstdlib>
#include <cstring>
#include <string>

using namespace std;

class Link {
string key;
Link *next;

public:
    Link(string key);

    void setValue(char);
    void setNext(Link *next);
    string getValue();
    Link *getNext();
    void printList();

};

链接.cpp

#include <cstdlib>
#include <string>
#include <iostream>
#include "Link.h"

using namespace std;

Link::Link(string key) {
    this->key = key;
next = NULL;

}

void Link::setNext(Link *l) {
cout << "setting new link "<<endl;
next = l;

cout<< "New link was set" << endl;
}

string Link::getValue() {
return key;

}

Link *Link::getNext() {
return next;
}

哈希.h

#include <iostream>
#include <cstring>
#include <string>
#include "LinkedList.h"

using namespace std;

class Hash{
    //100 slot array for hash function
    LinkedList *hashFN[100];

    //preset prime number                                                               
  int prime = 101;
    int key;
  unsigned int location;

public:
    //Note: Both the key & values are the same 
    void insert(string key, string value);
    // void deleteItem(int key);
    // char* find(int key);


};

哈希.cpp:

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

using namespace std;

void Hash::insert(string k, string v){
    //Get Hash for argv[2] aka value                                                  
  size_t key = std::hash<string>()(k);
   unsigned int location;

//check 1                                                                         
  cout << "Hash: " << key << endl;

  //Find location
  location = key % prime;

  //check 2                                                                         
  cout << "Mod 101 Hash: " << location << endl;

    hashFN[location]->addFront(k);
    cout << "Success!" << endl;

}

// void Hash::deleteItem(int key){
//  return;

// }

// char* Hash::find(int key){
//  return;

// }

main.cpp

#include <iostream>
#include <functional>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include "Hash.h"                                                                   

using namespace std;

int main(int argc, char *argv[]) {

  Hash HashTable;                                                                   


  string Insert = string("insert");
  string Delete = string("delete");
  string Find   = string("find");
  string Argv(argv[2]);  //Makes the argv[2] into string type

  // check for Request & string parameters                                            
  if(argc != 3) {
    cout << "Run program with 2 parameters. [Lower Case]" << endl;
    cout << "[1] insert, find, or delete" << endl;
    cout << "[2] string" << endl;
    exit(1);
  }

  //Check for "insert"                                                                
  if(strcmp(argv[1], "insert") == 0) {


  HashTable.insert(Argv, Argv);                                                

  }

  return 0;
}

【问题讨论】:

  • LinkedList的头文件和cpp文件是一样的。检查你的帖子。我怀疑您没有在LinkedList::LinkedList() 构造函数中将head 链接指针初始化为NULL,但需要确认/拒绝的文件恰好是未发布的文件。
  • 请养成使用所有警告和调试信息编译 C++ 代码的习惯(例如 Linux 上的 g++ -Wall -g),并学习使用调试器(Linux 上的 gdb)。
  • 向我们展示你的 LinkedList.cpp 文件,我希望你在构造函数中初始化为 NULL。
  • 抱歉修复了 LinkedList.cpp
  • @user2017327 您的代码中是否有anywhere 复制 LinkedList 对象?这包括将值传递给函数,或者将一个变量从一个变量复制到另一个变量?我问是因为您的LinkedList 课程练习Rule of Three,除非您正确地拥有适当的析构函数、赋值运算符、和 i> 复制构造函数。

标签: c++ linked-list


【解决方案1】:

您的直接问题:哈希表中的链表数组是一个指针数组。声明为:

LinkedList *hashFN[100];

您似乎从未分配任何这些对象。所以你只有一个包含 100 个指向垃圾的不确定指针的指针数组。要么分配它们,要么更好地直接实例化它们:

LinkedList hashFn[100];

这将要求您更改对它们的引用,例如

hashFN[location]->addFront(k);

变成这样:

hashFN[location].addFront(k);

接下来,您将使用非常量成员变量 prime 作为散列函数的模数。由于这是硬编码为101,因此您的表格需要具有相同的大小。 (事实上​​,我会完全丢失成员变量,而只是 Hash.cpp 文件中的一个静态常量)。但除此之外,问题仍然存在。你的桌子太小了一个槽。您的模数可以来自0..100,这意味着您需要一个大小为[101] 的表来处理所有这些插槽。请记住,C/C++ 中的数组是 [0...(n-1)] 为大小为 n 的数组寻址的

所以至少要像这样声明你的表:

LinkedList hashFN[101];

我要发布的最后一件事。你的链表像泰坦尼克号一样泄露。当列表被销毁时,您需要清理所有这些节点。在你的类中声明一个析构函数:

virtual ~LinkedList();

并在您的 .cpp 文件中像这样实现它:

LinkedList::LinkedList()
{
    while (head)
    {
        Link *victim = head;
        head = head->getNext();
        delete victim;
    }
}

好的。我撒了谎。还有一件事,在您能够舒适地阅读了解Rule of Three 之前,您应该使您的课程不可复制。将以下内容放在 LinkedList 类声明的私有部分中:

class LinkedList
{
   ... other code...

private:
    LinkedList(const LinkedList&);
    LinkedList& operator =(const LinkedList&);
};

这将隐藏可能导致您主要问题的事情,直到您准备好正确实施它们。如果您发现自己遇到了“无法访问私有成员LinkedList(const LinkedList&amp;)”的错误,那么您正在尝试制作副本,并且没有适当保护您的头指针,那是不行的。阅读三法则

剩下的交给你。

注意:使用标准库(std::vector&lt;&gt;std::unordered_map&lt;&gt; 等)有很多方法可以更轻松地完成这些工作。事实上,std::unordered_map&lt;&gt; 的替代品所有这些。但是,如果您只是对使用该语言再次熟悉感兴趣,那么深入了解一下裸机也不错。只需专注于重新学习,然后学习使用标准库必须提供的所有漂亮代码。

【讨论】:

  • 好酷我想知道我是否必须为这些对象分配内存
  • @user2017327 还有更多,如果您发现这对您有帮助,请给您的服务员小费(这将是答案左侧的投票和/或复选标记。但我还有更多,从你的素数和表大小开始(你差一)。
  • 非常感谢这修复了它!我用 C++ 编码已经快一年了哈哈
  • 我想我需要更多的声誉
  • @user2017327 阅读有关您的表大小的更多信息(它太小)。我还为您的链表类发布了一个析构函数。剩下的留给你(阅读我发布的“三法则”链接)。最后,您可以根据需要标记答案(标题附近答案左侧的绿色复选标记)。
猜你喜欢
  • 2012-05-08
  • 2018-10-03
  • 1970-01-01
  • 2012-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-06
  • 1970-01-01
相关资源
最近更新 更多