【问题标题】:C++ Segmentation fault when trying to print linked list node string尝试打印链表节点字符串时出现 C++ 分段错误
【发布时间】:2015-10-08 07:00:40
【问题描述】:

我正在创建一个基于链表的堆栈并且我正在使用类模板。我想通过用户输入定义堆栈的head 节点,然后打印它,但是我收到了分段错误,并且在找出原因时非常迷茫。

TowerHanoi.cpp 使用以下函数创建一个字符串,然后尝试将其存储在一个节点中,然后使用 push() 将其存储在堆栈中,这会将其添加到链接的“head”节点列表。在尝试打印链接列表的头节点时,我收到分段错误:

rod[]指的是一个LStack对象数组,其中包含Linked List以及查询和修改Linked List的成员函数。

    void TowerHanoi::set_Discs(size_t disc) {
    node<string>* temp= new node<string>();

    while (disc != 0) {
        string tmp_str;

        for (size_t i=0; i<disc; i++) {
            tmp_str.append("x");

        }
        disc--;
    temp->set_data(tmp_str);
    rod[0].push(temp);

    node<string>* tmp_node1 = rod[0].top();
    cout << "test: " + tmp_node1->data() << endl;
    }
}

LStack.template 包含'push()' 的定义:

    namespace oreilly_A2 {

    template <typename Item>
    LStack<Item>::LStack() {
        list = new LinkedList<Item>();
    }


    //push
    template <typename Item>
    void LStack<Item>::push(Item* head_in) {
        list->addToHead(head_in);
        used++;
    }


    //top
    template <typename Item>
    Item* LStack<Item>::top() {
        return list->list_getHead();
    }

LinkedList.template 在构造函数中初始化head 节点并包含addToHead(Item* entry) 函数:

namespace oreilly_A2 {

    template <typename Item>
    LinkedList<Item>::LinkedList() { //constructor initializing nodes
        head= new node<std::string>();
        tail= new node<std::string>();
        current= new node<std::string>();

    }


    template <typename Item>
    void LinkedList<Item>::addToHead(Item* entry) {
        Item* temp = head;
        head = entry;
        head->set_link(temp);
    }

Node.template 将nextprevious 节点初始化为NULL,并包含set_data() 函数:

namespace oreilly_A2 {


    template <typename Item>
    node<Item>::node() {
        next= NULL;
        previous= NULL;
    }

    template <typename Item>
    void node<Item>::set_data(Item new_data){
            word = new_data;
    }

template <typename Item>
Item node<Item>::data() const {  //return the word
        return word;
}

【问题讨论】:

  • 请尝试使用调试器来捕获崩溃,并在这样做时将代码缩小到崩溃的位置(以及相关的代码和上下文)。 the rules of three/five/zero 也可能存在问题。
  • 那么,您是否已经使用调试器找到了确切的源代码?
  • 什么是rod?你是怎么定义的?
  • 您真的只想创建一个项目 (temp) 并多次推送同一个项目吗?您的堆栈实现不支持。
  • rod 是一个 LStack 对象 Hades。黑暗,我想我应该在 addToHead 函数中创建另一个临时节点,它使用新数据创建 temp 副本并将其存储?

标签: c++ class templates fault


【解决方案1】:

在由LStack&lt;Item&gt;::push 调用的LinkedList&lt;Item&gt;::addToHead 函数中,它使用传入的node 并通过将其next 指针设置为链表头将其放入链表中。这意味着传入的节点现在是列表的一部分。

当您的set_discs 函数再次循环时,它会更改temp 的值并再次将其压入堆栈。但是temp指向的节点已经在栈上了!这意味着它最终会指向自己,这肯定会导致一些问题。

您可能想要解决此问题的一种方法是每次循环为temp 分配一个新对象,但这意味着LinkedList 的用户知道他必须分配每次都有新项目。

更好的方法是考虑使用LinkedListLStack 的人不需要知道它是如何存储的,因此他们根本不需要与node 交互。考虑将LinkedListLStack 的方法更改为仅获取Item 参考。然后他们可以构建自己的节点来存储数据。比如:

template <typename Item>
void LinkedList<Item>::addToHead(Item &entry) {
    node<Item>* temp = head;
    head = new node<Item>;
    head->set_date(Item);
    head->set_link(temp);
}

同样,将您的LStack 更改为只取一个Item &amp; 并将其传递给LinkedList

然后将您的rod 设为LStack&lt;string&gt; 的数组(或任何集合),而不是您现在拥有的,我怀疑它是LStack&lt;node&lt;string&gt;&gt; 的数组。

然后,您无需在主循环中进行任何分配,只需将普通的std::stringtmp_string 将按原样执行)传递给push 函数。

还有一件事,除非您这样做是为了学习制作链表(或为一个类),否则请考虑只使用 stl 类,例如 std::stack。一般来说,使用库类比使用自己的类要好得多,除非有充分的理由(比如学习)。

【讨论】:

  • 是的,我将其更改为,作为测试,只需创建一个字符串(无 while 循环),将字符串传递给 list->addToHead(),后者将字符串传递给头节点。我还修改了它以获得您对 addToHead() 的建议,但我仍然遇到分段错误!我疯了..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-18
  • 2012-07-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-26
相关资源
最近更新 更多