分段错误,在单链接列表中插入节点

时间:2014-12-03 18:29:07

标签: c++ insert segmentation-fault nodes singly-linked-list

我已经编写了一些代码,用于在第34页的单个链接列表中插入节点。位置,但当我运行项目时,我收到一个分段错误:11

当n == to sizeM时,我调用push_back,它将进入最后插入节点。当n ==到0时,我调用push_font,它将在开始时输入插入节点。这两个函数都可以工作,因为我已经调用它们在我的主文件中检查。在我进行任何调用之前,我的列表包含

440 330 110

headM指向440,这是列表中的第0个位置。

然后我进行3次调用以插入

刀片(40.3)

插入件(10,0)

插入件(33,2)

现在的名单应为10 440 33 330 110 40

我不确定出了什么问题,但我确信在插入33时我会做点什么。

这是我的simpleList.h,包含类

#ifndef Lab9_Simple_List__SimpleList__
#define Lab9_Simple_List__SimpleList__

typedef int ListItem;

class SimpleList {
private:

class Node {
public:
    ListItem item;
    Node *next;
};

Node *headM;
int sizeM;

void destroy();
// Deallocate all nodes, and sets headM to zero.

void copy(const SimpleList& source);
// List becomes copy of source.

public:

SimpleList(): headM(0), sizeM(0) { /* Point one */}
// PROMISES: creates empty list.

SimpleList(const SimpleList& source) { copy(source); }// copy constructor

SimpleList& operator =(const SimpleList& rhs);  // assignment operator

~SimpleList() { destroy(); }   // destructor

int size() const {return sizeM;}

void push_back(const ListItem& item);
// PROMISES:
//    Adds a node with an item to the end of the list, and increments sizeM

void push_front(const ListItem& item);
// PROMISES:
//    Adds a node with an item to the beginning of the list, and increments
//    sizeM
void pop_back(const ListItem& item);
// PROMISES:
//    The last node int list is removed

const ListItem& at(int n)const;
// PROMISES:
//    An item is return at the nth position in the list.
//    if n is less than 0 or greater than or equal sizeM gives the error
//    message: "Illegal Access" and terminates the program

ListItem& at(int n);
// PROMISES:
//    An item is return at the nth position in the list.
//    if n is less than 0 or greater than or equal sizeM gives the error
//    message: "Illegal Access" and terminates the program

void insert(const ListItem& theItem, int n);
// PROMISES:
//    A node with a copy of theItem is inserted at the nth position, and sizeM
//    will be incremented if the operation of insert was successfull.
//    if n == sizeM calles push_back
//    if n == 0 calls push_front
//    if n < 0 or n > sizeM returns and does nothing.

void remove(int n);
//  PROMISES:
//    Does nothing if n < 0 or n > sizeM-1. Otherwise, if list is not empty
//    removes the node at the position n.
};

#endif /* defined(Lab9_Simple_List__SimpleList__) */

这是我的文件,其中包含成员定义,那些不工作的是插入函数

#include <iostream>
using namespace std;

#include <stdlib.h>
#include "SimpleList.h"


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

sizeM = rhs.sizeM;
return *this;
}

ListItem& SimpleList::at(int n)
{
if(n < 0 || n >= sizeM)
{
    cout << "\n Illegal Access. Program Terminates...";
    exit(1);
}

Node * p = headM;
for(int i= 0; i < n; i++)
    p = p -> next;

// point four

return p -> item;
}

const ListItem& SimpleList::at(int n)const
{
if(n < 0 || n >= sizeM){
    cout << "\n Illegal Access. Program Terminates...";
    exit(1);
}

Node * p = headM;
for(int i= 0; i < n; i++)
    p = p -> next;

// point three - when reached for the first time
return p -> item;
}

void SimpleList::push_back(const ListItem& item)
{
Node *new_node = new Node;
if(new_node == NULL)
{
    cout << "\nNo memory available to create a node" << endl;
    exit(1);
}

new_node->item = item;

if (headM == 0) {
    new_node->next = headM;
    headM = new_node;
}
else
{
    Node* p = headM;
    while (p ->next  != NULL)
        p = p ->next;

    p -> next = new_node;
    new_node -> next = NULL;
}
sizeM++;

// point five - when reached for the third time
}


void SimpleList::push_front(const ListItem& item)
{
Node *new_node = new Node;
new_node->item = item;
new_node->next = headM;
headM = new_node;
sizeM++;

// point two
}

void SimpleList::destroy()
{

// This function is not properly designed.
cout << "\nSimpleList::destroy was called but didn't do the right job.";
headM = 0;
}


void SimpleList::copy(const SimpleList& source)
{

// this function is incomplete and is not properly designed. It doesnt do
// its job, makeing 'this' SimpleList object a copy of the scoure.

// The only effect of the next line is to tell the compiler
// not to generate an "unused argument" warning.  If you are going to complete
// this funciton, don't leave it in your solution.
(void) source;

cout << "\nSimpleList::copy was called but didn't do the right job."
<< "--program is terminated.\n";
exit(1);
}

void SimpleList::insert(const ListItem& theItem, int n)
{
if (n < 0 || n > sizeM)
    return;
else if (n == sizeM)
    push_back(theItem);
else if (n == 0)
    push_front(theItem);
else
{
    Node* new_node = new Node;
    new_node->item = theItem;
    Node* temp = headM;
    for(int i = 0; i < (n - 1) ; i++)
    {
        temp = temp->next;
    } 
    new_node->next = temp->next;
    temp->next = new_node;
    sizeM++;
}
}

void SimpleList::remove(int n)
{
if( n < 0 || n > sizeM ) { 
    return;
}

Node* p = headM;

if(n == 0 && headM != NULL)
{
    Node* const p_doomed = headM;
    headM = p_doomed->next;
    delete p_doomed;
    --sizeM;
}
else{
    for(int c = 0; c < n - 1; c++ )
    {
        p = p->next;
    }
    Node* const p_doomed = p->next;
    p->next = p_doomed->next;
    delete p_doomed;
    --sizeM;
}
}

以下是我的主要文件

#include <iostream>
#include <iomanip>
using namespace std;
#include "SimpleList.h"
#define EXERCISE_B

void print(const SimpleList& list);
// PROMISES: prints values in the list from first node (node number 0) to
//           the last node. 

int main()
{    
SimpleList list;

cout << "\nList just after creation -- is empty.";

list.push_front(50);
cout << "\nAfter calling push_front. list must have: 50\n";
print(list);

list.push_back(440);

list.at(0) = 770;
cout << "\nAfter calling push_back and at functions, list must have: 770  440\n";
print(list);

list.push_back(330);
list.push_back(220);
list.push_back(110);

cout << "\nAfter three more calls to push_back, list must have:"
"770, 440, 330, 220, 110\n";
print(list);

#if defined (EXERCISE_B)
list.remove(0);
list.remove(2);
cout << "\nAfter removing two nodes. list must have: 440, 330, 110\n";
print(list);
list.insert(40, 3); //insert node with the value of 40 at the 4th position
list.insert(20, -1); // do nothing
list.insert(30, 30000); // do nothing
list.insert(10, 0); //insert node with the value of 10 at the 1st position
list.insert(33, 2); // insert node with the value 33 at the 3rd position

cout << "\nTwo  more nodes inserted, must have: 10, 440, 33, 330, 110, 40\n";
print(list);

list.remove(0);
list.remove(1);
list.remove(2);
list.remove(3);
list.remove(4);
list.remove(5);
cout << "\nAfter 6 removes, list must have: 440, 330, 40: \n";
print(list);

#endif
return 0;

}


void print(const SimpleList& list)
{
for(int i = 0; i < list.size(); i++)
    cout << list.at(i) << "  ";
}

这是我收到的输出

Haydns-MacBook-Pro:desktop Haydn$ g++ lab9_EXE_A.cpp simpleList.cpp
Haydns-MacBook-Pro:desktop Haydn$ ./a.out 

List just after creation -- is empty.
After calling push_front. list must have: 50
50  
After calling push_back and at functions, list must have: 770  440
770  440  
After three more calls to push_back, list must have:770, 440, 330, 220, 110    
770  440  330  220  110  
After removing two nodes. list must have: 440, 330, 110
440  330  110  
Two  more nodes inserted, must have: 10, 440, 33, 330, 110, 40
Segmentation fault: 11

1 个答案:

答案 0 :(得分:1)

问题出在void SimpleList::remove(int n)

的第一行
if (n < 0 || n >= sizeM) {  // CHange to >= and not > !!!

说明:

如果调用此函数时n0且列表已为空(表示sizeM==0headM==nullptr),则使用原始核心{{ 1}}会是假的。

这意味着该功能将继续,执行流程为:

n<0 || n>sizeM

如果调用该函数的时候... p=headM; // meaning that p is now nullptr if (n == 0 && headM != NULL) // false because `n==0 && headM==nullptr` // if block ignored else{ // here: (n!=0 || headM==NULL) for (int c = 0; c < n - 1; c++) // the condition is false // the loop body is ignored Node* const p_doomed = p->next; // ouch !!!! p is nullptr => segfault !!! 与您的n main()的{​​{1}}大小相当,那么情况类似。当remove(3)已经p->next时,您尝试访问p一次太多。