C ++链接列表分段错误

时间:2010-11-23 00:00:31

标签: c++

我正在编写一个程序作为学校的作业,虽然我已经解决了所有错误,直到我决定调用我的复制构造函数。该程序是交互式的(CLI),基本上有两个模块:LList类的.h和.cpp文件,程序结构的.h和.cpp文件,以及main()的第3个cpp文件。它被认为是一个水电工程公司(假公司)的程序,其中LList节点保存河流中的年度水流量(年和流量)的数据。以下是关于班级的一些见解:

//list.h
struct ListItem {
  int year;
  double flow;
};

struct Node {
  ListItem item;
  Node *next;
};

class FlowList {
public:
  FlowList();
  // PROMISES: Creates empty list

  FlowList(const FlowList& source);
    // REQUIRES: source refers to an existing List object
    // PROMISES: create the copy of source

  ~FlowList();
    // PROMISES: Destroys an existing list.

  FlowList& operator =(const FlowList& rhs);
  // REQUIRES: rhs refers to an existing FlowList object
  // PROMISES: the left hand side object becomes the copy of rhs

  //....Other member functions

private:
  // always points to the first node in the list.

  Node *headM;
  // Initially is set to NULL, but it may point to any node.

  Node *cursorM;
  //For node manipulation within interactive CLI

  void copy(const FlowList& source);

  void destroy();

我相信内存泄漏或碰撞发生在复制功能的某个地方,但不能指向哪里。

//list.cpp

FlowList::FlowList() : headM(0), cursorM(0) {}

FlowList::FlowList(const FlowList& source) 
{
  copy(source);
}

FlowList::~FlowList() 
{
  destroy();
}

FlowList& FlowList::operator =(const FlowList& rhs) 
{
  if (this != &rhs)
  {
    destroy();
    copy(rhs);
  }
  return (*this);
}

//...more function definitions

void FlowList::copy(const FlowList& source)
{
  if (source.headM == NULL) 
  {
    headM = NULL;
    cursorM = NULL; 
    return;
  }

  Node* new_node = new Node;
  assert(new_node);
  new_node->item.year = source.headM->item.year;
  new_node->item.flow = source.headM->item.flow;
  new_node->next = NULL;    
  headM = new_node;

  Node* thisptr = new_node;

  for(Node* srcptr = source.headM->next; srcptr != NULL; srcptr = srcptr->next)
  {
    new_node = new Node;
    assert(new_node);
    new_node->item.year = srcptr->item.year;
    new_node->item.flow = srcptr->item.flow;
    new_node->next = NULL;
    thisptr->next = new_node;
    thisptr = thisptr->next;
  }   

}

void FlowList::destroy()
{
  Node* ptr = headM;
  Node* post = headM->next;

  while (ptr != NULL)
  {
    delete ptr;
    ptr = post;
    if (post)
       post = ptr->next;
  }
  headM = NULL;
}

如果我创建一个FlowList对象,用.dat文件中的数据填充它,该程序可以正常工作;然后,我可以操作程序中的数据(显示,执行计算,添加到列表,从列表中删除并将数据保存到文件)但如果我创建另一个FlowList对象(在main.cpp中),程序崩溃(分段错误)。 任何帮助将非常感激。

1 个答案:

答案 0 :(得分:4)

我发现的最初的事情是,如果列表为空,看起来destroy()函数总是会出现分段错误:

void FlowList::destroy()
{
  Node* ptr = headM;
  Node* post = headM->next;
  //...
}

如果列表为空,headMNULL,那么您正在尝试执行headM->next,在这种情况下会始终产生分段错误。

如果您传入一个空列表,我认为您的复制构造函数中也可能存在内存泄漏。如果你看一下这段代码:

void FlowList::copy(const FlowList& source)
{
  if (source.headM == NULL) 
  {
    headM = NULL;
    cursorM = NULL; 
    return;
  }
  //...
}

如果当前列表包含20个项目并且source是空列表怎么办?您将当前列表的headMcursorM设置为NULL,但您永远不会在当前列表中最初使用的任何节点上调用delete new创造。您可能希望将destroy()函数也放在复制构造函数中(您为operator=函数执行了此操作)。

我注意到的最后一件事是你没有为cursorM函数中的非空列表初始化copy()(@Akusete也指出了这一点)。我想我建议您在复制构造函数的开头,只需将cursorMheadM初始化为NULL,以覆盖您的基础。

看起来你真的很亲近,我认为你真的需要考虑处理空列表的边界情况(在LHS和RHS上),你可能会发现大部分这些错误。祝你好运!