segmentation fault 11

Hi im getting segmentation fault 11 if I delete the NULL pointer from a link list what would I return if the list is empty?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <cstddef>
#include <initializer_list>
#include <iostream>

template <typename T>
class LinkedList {
  struct Node;  
 public:
  LinkedList() {
    std::initializer_list<T> empty;
  }

std::size_t Size() const {
    return size;
  }

  void RemoveFront() {
    Node* front = this->start;
    this->start = front->next;
    delete front; 
  }

  T& Front() const {
    if (Size() <= 0) {
      throw std::domain_error("List is empty");
    }
    Node* Front = start;
    return Front->data;
  }

private:
  struct Node {
    T data;
    Node* next = nullptr;
    Node* prev = nullptr;
  };
  Node* start = nullptr;
  Node* end = nullptr;
  std::size_t size = 0;
};

int main() {
LinkedList<char> test;
test.RemoveFront();
test.Front();
}
Last edited on
I would throw an exception.
If your compiler supports C++17 you could return a std::optional.

BTW in your RemoveFront() function you need to check if the list is not empty.
If your compiler supports C++17 you could return a std::optional.

One problem with optional is that it doesn't support references. You can of course return a std::optional<std::reference_wrapper<T>> but that becomes very verbose (and I don't really see the advantage to be honest) so I would be tempted to just return a pointer in these situations.
Last edited on
What do the ints do? I.e. what does the std::list do in similar situation?

http://www.cplusplus.com/reference/list/list/front/
If the container is not empty, the function never throws exceptions (no-throw guarantee).
Otherwise, it causes undefined behavior.


http://www.cplusplus.com/reference/list/list/pop_front/
If the container is not empty, the function never throws exceptions (no-throw guarantee).
Otherwise, it causes undefined behavior.


In other words, the it is the responsibility of the user to not call these on empty list. They could throw exception, for the user is irresponsible, but choose not to.


delete nullptr; should be safe and well defined. Your undefined behaviour is from elsewhere.


PS.
1. What is the purpose of line 45?

2. What is odd in:
1
2
3
4
5
T foo() {
  U bar;
  // code
  return bar;
}

(You do have that construct in your code.)
At line 45 you have LinkedList::size, but you don't appear to use it. This should maintain the size of the list. The Size() method should simply return this->size;

Where there's a next, there's a prev. Where there's a start, there's an end. What I mean is that any time you deal with next, you should ask yourself about prev, and anytime you deal with start, you should ask about end.

Specifically, RemoveFront needs to set the prev pointer of the new starting element.
And it needs to set "end" if you remove the only item in the list.
so I reedited the code is it suppose to say teminating with uncaught exception of type std::domain_error: List is empty is there a way to catch the error and fix it.
or am I able to return nothing if the list is empty?
You can catch the exception in main.
1
2
3
4
5
6
7
8
9
10
11
12
13
int main() 
{
  LinkedList<char> test;
  try
  {
    test.RemoveFront();
    test.Front();
  }
  catch(const exception& ex)
  {
    cerr << "Error: " << ex.what() << '\n';
  }
}

Since you return a reference you can't return nothing. A reference is referring to an existing var.
If you would return a pointer you could return nullptr like in old C, but I don't think that's a good idea.
It's too easy to ignore return values. The preferred way in C++ is to throw exceptions.
Have a look at the CPP Core Guidelines:
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-errors
Are you still using the same main() program in your original post? That creates an empty list, attempts to remove an item from it, and then gets a reference to the first item in the list. What do you expect this code to do?

It's perfectly fine to say that some methods will create undefined behavior in some circumstances. You just need to make that decision and preferably document it in the code. For example, if Front() returns a reference then you pretty much must say that calling it on an empty list will create undefined behavior (or throw an exception as you've done).

You should probably write a method to insert an item into a list. You can't really test Front() or RemoveFront() unless you can put something in the list first.
Topic archived. No new replies allowed.