返回组件时出现链表分段故障

Linked List Seg Fault when Returning Component

本文关键字:链表 分段 故障 组件 返回      更新时间:2023-10-16

我正在为我的c++类编写一个程序,它基本上是一个小型书店应用程序。书店将有一个成员链接列表(ListMemberType)和一个图书链接列表(ListBookType)。链表的每个节点都由一个到下一个零部件的链接和一个零部件组成。该组件的类型为BookType。

这是ListBookType 的头文件

#include "bookType.h"
typedef BookType ItemType;    // Type of each component
struct NodeType;              // Forward declaration
class ListBookType {
public:
const ListBookType& operator=(const ListBookType& rightObject);
//overload assignment operator
//will set the left side equal to right side
void Replace(ItemType theNewItem, ItemType theOldItem);
//Pre:These are the same book(ISBN is the same)
//Post: old component will be replaced with the new component
ListBookType();
// Constructor
// Post: Empty list has been created
~ListBookType();
// Destructor
// Post: All nodes are returned to the heap
ListBookType(const ListBookType& otherList);
// Copy constructor
// Post:  A deep copy of otherList is created and dataPtr is the
//        external pointer to this copy
// Action respnsibilities
void Insert(ItemType item);
// Pre:  List is not full and item is not in the list
// Post: item is in the list and length has been incremented
void Delete(ItemType item);
// Post: item is not in the list
void ResetList();
// The current position is reset to access the first item in the list
ItemType GetNextItem();
// Assumptions:  No transformers are called during the iteration.
// There is an item to be returned; that is, HasNext is true when
// this method is invoked
// Pre:  ResetList has been called if this is not the first iteration
// Post: Returns item at the current position.
// Knowledge responsibility
int GetLength() const;
// Post: Returns the length of the list
bool IsEmpty() const;
// Post: Returns true if list is empty; false otherwise
bool IsFull() const;
// Post: Returns true if list if full; false otherwise
bool IsThere  (ItemType item ) const;
// Post: Returns true if item is in the list and false otherwise
bool HasNext() const;
// Returns true if there is another item to be returned; false
// otherwise
ItemType GetBook(ItemType bookToGet)const;
//Pre: Book is in list
//Post: the book is returned
//Pre: Book is in the list
//Post: Book with matching ISBn will be returned
private:
NodeType* dataPtr;     // Pointer to the first node in the list
int length;
NodeType* currentPos;   // Pointer to the current position in a traversal
NodeType* lastPtr;
};

这是我知道的规范文件中包含我的错误的部分,以及我认为可能导致错误的部分。

#include "listBookType.h"
#include "bookType.h"
#include <iostream>
#include <cstddef>           // For NULL
using namespace std;
typedef NodeType* NodePtr;
struct NodeType {
ItemType component;
NodePtr link;
};
const ListBookType& ListBookType::operator=(const ListBookType& rightObject) {
cout<<"Assignment operator bookList"<<endl;
NodePtr fromPtr;    // Pointer into list being copied from
NodePtr toPtr;      // Pointer into new list being built
if(this != &rightObject) {
if (rightObject.dataPtr == NULL) {
dataPtr = NULL;
return *this;
}
// Copy first node
fromPtr = rightObject.dataPtr;
dataPtr = new NodeType;
dataPtr->component = fromPtr->component;
// Copy remaining nodes
toPtr = dataPtr;
fromPtr = fromPtr->link;
while (fromPtr != NULL)
// Copying nodes from original to duplicate
{
toPtr->link = new NodeType;        // Store new node in link of last
// node added to new list
toPtr = toPtr->link;           // toPtr points to new node
toPtr->component = fromPtr->component; // Copy component to new node
fromPtr = fromPtr->link;       // fromPtr points to next node
// of original list
}
toPtr->link = NULL;
lastPtr = toPtr;      // Set last pointer
}
return *this;
}

ItemType ListBookType::GetBook(ItemType bookToGet)const {
NodePtr currPtr = dataPtr;      // Loop control pointer
NodePtr tempPtr = NULL;
while (currPtr != NULL && currPtr->component != bookToGet
&& currPtr->component < bookToGet) {
tempPtr = currPtr;
currPtr = currPtr->link;
}
cout<<"right before return of getBook"<< endl;
return tempPtr->component;
}
ListBookType::ListBookType(const ListBookType& otherList) {
cout<<"copy construct book list"<< endl;
NodePtr fromPtr;    // Pointer into list being copied from
NodePtr toPtr;      // Pointer into new list being built
if (otherList.dataPtr == NULL) {
dataPtr = NULL;
return;
}
// Copy first node
fromPtr = otherList.dataPtr;
dataPtr = new NodeType;
dataPtr->component = fromPtr->component;
// Copy remaining nodes
toPtr = dataPtr;
fromPtr = fromPtr->link;
while (fromPtr != NULL) { // Copying nodes from original to duplicate
toPtr->link = new NodeType;       // Store new node in link of last
// node added to new list
toPtr = toPtr->link;          // toPtr points to new node
toPtr->component = fromPtr->component; // Copy component to new node
fromPtr = fromPtr->link;      // fromPtr points to next node
// of original list
}
toPtr->link = NULL;
lastPtr = toPtr;     // Set last pointer
}

ListBookType::~ListBookType() {
cout<< "destructor book list"<< endl;
NodePtr tempPtr;
NodePtr currPtr = dataPtr;
while (currPtr != NULL) {
tempPtr = currPtr;
currPtr = currPtr->link;
delete tempPtr;
}
}

我遇到的问题在GetBook(ItemType bookToGet)中。我找到了这个问题,当我返回tempPtr->component时,我出现了seg错误。我在代码的其他几个地方也遇到了同样的问题,我不知道为什么我在这里出现seg错误,也不知道潜在的问题是什么。(注意:BookType类不包含任何需要重载赋值运算符或复制构造函数的动态数据)

如果有任何帮助,我将不胜感激。我觉得我只是错过了一些我不知道的重要事情。

GetBook例程中,考虑dataPtr已经为NULL的情况

您将访问return tempPtr->component;//导致segfault。

dataPtr为NULL时,您应该单独处理这种情况。

while (currPtr != NULL && currPtr->component != bookToGet // dataPtr = currPtr is NULL 
&& currPtr->component < bookToGet){
tempPtr = currPtr;
currPtr = currPtr->link;
}
cout<<"right before return of getBook"<< endl;
return tempPtr->component; // SEGFAULT!

如果while语句中的条件在第一次求值时为false,则tempPtr将永远不会设置为除NULL之外的任何值,并且return语句中的tempPtr->component尝试取消引用空指针并崩溃。

考虑一下,如果while条件第一次为false,那么函数返回的合理默认值是什么,然后如果tempPtr在return语句之前为NULL,则返回该默认值。