【问题标题】:Merging two linked lists yielding seg faults, etc合并两个链表产生段错误等
【发布时间】:2015-04-24 15:53:06
【问题描述】:

我正在创建一个状态对象的链接列表,每个状态对象都包含一个居住在该状态中的常驻对象的链接列表。用户读入一个数据库文件,然后可以从一些命令中进行选择,例如寻找一个人、移动一个人或将两个状态合并为一个全新的状态。当我尝试合并 2 个州的人时,我必须创建一个新州,将所有人从第一个州的居民名单移动到新州的居民名单,并对第二个州的居民名单做同样的事情。然后,这些人应该出现在新州的居民名单中,而不是原州的居民名单中。我收到一堆错误:当我尝试合并时,我收到重复的空闲块警告;当用户尝试将新州的居民名单作为命令打印出来时,没有人被列出;此外,当用户尝试打印任一原始州的驻留列表时,会打印前几个,但随后出现设置错误,核心被转储,程序停止运行。任何帮助将不胜感激。

在我的列表对象中:

void addLink (Link <type> * data) {
    if (first == NULL) {
        first = data;
        last = data;
    }
    else {
        last->next = data;
        last = data;
    }
}

如果输入的命令是“合并”...

else if (cmd == "merge") {
    string state1, state2, newstate;
    cin >> state1 >> state2 >> newstate;
    State * ns = state_ls->addLink(new State(newstate))->data;
    Link <State*> * s1 = searchList(state1, state_ls);
    Link <State*> * s2 = searchList(state2, state_ls);
    List <Person*> people1 = s1->data->res_list;
    List <Person*> people2 = s2->data->res_list;
    List <Person*> newres_list = ns->res_list;
    Link <Person*> * temp = people1.first;
    while (temp != NULL) {
        newres_list.addLink(temp);
        temp = temp->next;
        }
    temp = people2.first;
    while (temp != NULL) {
        newres_list.addLink(temp);
        temp = temp->next;
        }
}

【问题讨论】:

  • 您正在列表之间共享链接。当其中一个列表被销毁时,这很可能是一个问题。大量的指针表明您在生命周期管理方面存在更多问题。你有没有考虑过不要这么依赖指针?
  • 大多数其他学生完成作业的方式是使用指针。指针对于链接是必不可少的,指向链接中数据(即我的人员和状态结构)的指针使许多早期的命令更容易测试和执行。但是,如果有特定的指针需要更改,请告诉我!

标签: c++ pointers merge linked-list segmentation-fault


【解决方案1】:

代码中的一些问题可能是导致问题的原因:

  1. 您没有检查searchList() 的结果。如果您输入的状态不存在并且返回 NULL 怎么办? addLink() 也一样,如果它可能失败。
  2. people1people2newres_list 是原始列表的副本。根据这些类的实现方式,这可能很糟糕或非常糟糕。您可能想在此处使用指针或引用,例如:

    List <Person*>& people1 = s1->data->res_list;
    List <Person*>& people2 = s2->data->res_list;
    List <Person*>& newres_list = ns->res_list;
    
  3. 如果您希望将人员从原始状态移动到新状态,则需要在移动人员后重置人员列表头/尾。大概是这样的:

    s1->person->data->res_list->first = NULL;
    s1->person->data->res_list->last = NULL;
    s2->person->data->res_list->first = NULL;
    s2->person->data->res_list->last = NULL;
    

更新 -- 您似乎对链表指针和从多个列表中添加/删除节点有点困惑。如果我们看一个简单的例子:

List<Person*>* Person1 = new List<Person*>;
List<Person*>* Person2 = new List<Person*>;
List<Person*> List1;
List<Person*> List2;

List1.addLink(Person1);
List1.addLink(Person2);   //Ok: List1 has two persons

List2.addLink(Person1);   //Error: Person1 can't belong to both lists

在您尝试将已经在一个列表中的节点添加到另一个列表之前,一切都很好。这将“弄乱”两个列表中的节点 next 指针。

另一个困惑似乎是如何将所有元素从一个列表移动到另一个列表。您所要做的就是设置两个列表的头/尾,例如将所有节点从 List1 移动到 List2 只需这样做:

List2.first = List1.first;
List2.last  = List1.last;
List1.first = NULL;
List1.last  = NULL;

您不需要触摸 List1 中的各个节点,因为您没有更改它们的指针位置。如果您想将所有节点从 List1 复制到 List2,则有点不同,因为您必须创建新节点。

如果您对更正后的代码仍有问题,我建议您将其简化为一个展示问题的小示例并发布另一个 SO 问题。

【讨论】:

  • 太棒了!这解决了大部分问题。我一直忘记传递指针只会复制东西。谢谢!既然这些人都在新列表中,如果我想从旧列表中删除这些人......?仅迭代一个删除列表中链接的方法是否足够,或者是否还有需要删除的指针?
  • 实际上,有些奇怪的事情正在发生。正如你所说,我做了这三个列表参考;当我列出新州的人时,一切都很好。当我列出第二个州的人员名单时,那个州的每个人都还在,这是意料之中的。但是,当我列出第一个州的人员名单时,来自两个州的每个人现在也在该名单中。发生了什么?!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-26
  • 2019-06-19
  • 2015-08-13
  • 2013-07-18
  • 1970-01-01
相关资源
最近更新 更多