我正在编写一个程序作为学校的作业,虽然我已经解决了所有错误,直到我决定调用我的复制构造函数。该程序是交互式的(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中),程序崩溃(分段错误)。 任何帮助将非常感激。
答案 0 :(得分:4)
我发现的最初的事情是,如果列表为空,看起来destroy()
函数总是会出现分段错误:
void FlowList::destroy()
{
Node* ptr = headM;
Node* post = headM->next;
//...
}
如果列表为空,headM
为NULL
,那么您正在尝试执行headM->next
,在这种情况下会始终产生分段错误。
如果您传入一个空列表,我认为您的复制构造函数中也可能存在内存泄漏。如果你看一下这段代码:
void FlowList::copy(const FlowList& source)
{
if (source.headM == NULL)
{
headM = NULL;
cursorM = NULL;
return;
}
//...
}
如果当前列表包含20个项目并且source
是空列表怎么办?您将当前列表的headM
和cursorM
设置为NULL
,但您永远不会在当前列表中最初使用的任何节点上调用delete
new
创造。您可能希望将destroy()
函数也放在复制构造函数中(您为operator=
函数执行了此操作)。
我注意到的最后一件事是你没有为cursorM
函数中的非空列表初始化copy()
(@Akusete也指出了这一点)。我想我建议您在复制构造函数的开头,只需将cursorM
和headM
初始化为NULL
,以覆盖您的基础。
看起来你真的很亲近,我认为你真的需要考虑处理空列表的边界情况(在LHS和RHS上),你可能会发现大部分这些错误。祝你好运!