简体   繁体   中英

Segfault when recursively searching a linked list in c++

A section of one of my assignments asks for me to recursively search through a list to see if a double is in it. It prints a string about whether it is in the list or not, but after it finishes the cycle it crashes and says there was a segmentation fault. The following is the isolated section of the code that uses the recursive method.

class Header
{
protected:
 //Create the struct for the list
 struct ListNode {
   double x;
   ListNode *next;
   ListNode(double v1, ListNode *n1 = nullptr) {
     double x = v1;
     next = n1;}
 };
 ListNode *head;

public:
 Header()
 {head = nullptr;}

 //Add doubles to the list
 void add(double var) {
  if(head == nullptr)
  {head = new ListNode(var);}

  else {
    ListNode *nodePtr = head;

    while(nodePtr->next != nullptr)
    {nodePtr = nodePtr->next;}

    nodePtr->next = new ListNode(var);
  }
 }

 //Call the function that performs the recursive function
 void recursiveMember(double var) const 
 {recursiveMember(head, var);}

private:
 //This is where the issue is
 void recursiveMember(ListNode *aList, double var) {
   if(aList == nullptr)
   {cout << var << " is not in the list" << endl;}

   if(var != aList->x)
   {recursiveMember(aList->next, var);}

   else
   {cout << var << " is in the list" << endl;}
 }
};

int main()
{
  //Create the object
  Header vars;

  //Populate the object
  vars.add(1.1);
  vars.add(2.2);
  vars.add(3.3);

  //Call the recursive function
  vars.recursiveMember(1.1);
  vars.recursiveMember(.5);

  return 0;
}

The program displays

1.1 is in the list
.5 is not in the list
Segmentation fault (core dumped)

This would not necessarily be a problem, but there is some other functionality that I need to perform after and the segfault causes the program to crash before performing that.

I was using the gdb debugger to isolate the error causing code, which is if(var != aList->x) to implement the recursive function.

Is there something about recursion I am missing?

You need to return from the recursiveMember function if aList is nullptr . Otherwise you are accessing invalid Nodes.

if(aList == nullptr)
{
  cout << var << " is not in the list" << endl;
  return;
}

Equivalently, you could enter the second if branch conditionally

if(aList == nullptr)
{
  cout << var << " is not in the list" << endl;
}
else if(var != aList->x)
// ...

Also, in your ListNode constructor, you are not assigning the data correctly

ListNode(double v1, ListNode *n1 = nullptr) {
     double x = v1;   // this x is a local variable
     next = n1;
}

Instead, you need to assign to the member x .

ListNode(double v1, ListNode *n1 = nullptr) {
     x = v1;   // this x is the member
     next = n1;
}

For starters, you may not call a non-constant member function from a constant member function. So the function shall be declared at least like

void recursiveMember(ListNode *aList, double var) const;

Secondly, the private member function accepts as argument a pointer to the head node si it should be declared as a static member function

static void recursiveMember(ListNode *aList, double var);

And thirdly the both functions private and public shall not to output any message. It is the caller of the functions decides whether to output anything. The function shall return a boolean value.

So the first function should be declared like

bool recursiveMember( double var ) const 
{
    return recursiveMember( head, var);
}

and the second function should be declared like

static bool recursiveMember( const ListNode *aList, double var);

Further, if the current value of the pointer aList is equal to nullptr nevertheless you are trying to use it to access memory in the second if statement

if(var != aList->x)
{recursiveMember(aList->next, var);}

That is there is no return from the function in the case when aList is equal to nullptr .

if(aList == nullptr)
{cout << var << " is not in the list" << endl;}

The function should be defined the following way

static bool recursiveMember( const ListNode *aList, double var ) 
{
    if ( aList == nullptr )
    {
        return false;
    }
    else if ( a:ist->var != var )
    {
        return recursiveMember( aList->next, var );
    }
    else
    {
        return true;
    }
}

And in main you should check the return value of the called function and output a corresponding message.

Pay attention to that within the constructor you are using the local variable x instead of the data member x

   ListNode(double v1, ListNode *n1 = nullptr) {
     double x = v1;
     next = n1;}

There must be

   ListNode(double v1, ListNode *n1 = nullptr) {
     x = v1;
     next = n1;}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM