Reputation: 29
So I'm trying to create a Linked List class to understand better how pointers and data structures work but I keep running into a -11 SIGSEGV error. When I looked up the error it said that I might be using dereferenced pointers or accessing an array out of its bounds but neither of those makes sense for my program. I've searched everywhere for similar issues but none of them seem to apply to my program. Can anyone else see what I'm doing wrong?
#include <stdexcept>
#pragma once
using namespace std;
#define NODE typename LinkedList<T>::Node*
template <typename T>
class LinkedList {
public:
void AddHead(const T& data); //Adds new node to the beginning of the list
void AddTail(const T& data); //Adds new node to the end of the list
LinkedList(); //Default constructor
LinkedList(const LinkedList<T>& list); //Copy constructor
struct Node {
/*Individual node that stores the data*/
T data;
Node* prev;
Node* next;
Node(); //Default constructor for node
Node(T _data); //Data constructor for node
Node(T _data, Node* _prev, Node* _next); //Full constructor for node
};
private:
NODE head = nullptr;
NODE tail = nullptr;
unsigned int count;
};
/*Function definitions*/
template <typename T>
void LinkedList<T>::AddHead(const T& data) {
NODE tempRef = new Node(data, nullptr, head);
head->prev = tempRef;
head = tempRef;
delete tempRef;
count++;
}
template <typename T>
void LinkedList<T>::AddTail(const T& data) {
NODE tempRef = new Node(data, tail, nullptr);
tail->next = tempRef;
tail = tempRef;
delete tempRef;
count++;
}
template <typename T>
LinkedList<T>::LinkedList() {
count = 0;
head = nullptr;
tail = nullptr;
}
template <typename T>
LinkedList<T>::LinkedList(const LinkedList<T>& list) {
this->head = list.head;
this->tail = list.tail;
this->count = list.count;
}
/*Node Constructors*/
template <typename T>
LinkedList<T>::Node::Node() {
next = nullptr;
prev = nullptr;
}
template <typename T>
LinkedList<T>::Node::Node(T _data) {
next = nullptr;
prev = nullptr;
data = _data;
}
template <typename T>
LinkedList<T>::Node::Node(T _data, Node* _prev, Node* _next) {
next = _next;
prev = _prev;
data = _data;
}
Upvotes: 1
Views: 999
Reputation: 311048
The both functions AddHead
and AddTail
have a serious bug because the allocated node is at once deleted
head = tempRef;
delete tempRef;
and
tail = tempRef;
delete tempRef;
So the pointers head and tail have invalid values.
Moreover the functions do not update tail
and head
correspondingly in each function.
And initially the both pointers are equal to nullptr
. So these statements
head->prev = tempRef;
and
tail->next = tempRef;
result in undefined behavior.
The function AddHead
can be defined the following way
template <typename T>
void LinkedList<T>::AddHead(const T& data) {
NODE tempRef = new Node(data, nullptr, head);
if ( head == nullptr )
{
head = tail = tempRef;
}
else
{
head = head->prev = tempRef;
}
count++;
}
And the function AddTail
can look like
template <typename T>
void LinkedList<T>::AddTail(const T& data) {
NODE tempRef = new Node(data, tail, nullptr);
if ( tail == nullptr )
{
tail = head = tempRef;
}
else
{
tail = tail->next = tempRef;
}
count++;
}
The copy constructor (and the copy assignment operator) either should be defined as deleted or shall make a deep copy of the list passed as the argument.
Otherwise two lists will try to delete the same nodes two times (in the forgotten by you destructor).
The structure Node
should be declared as a private class member.
Upvotes: 1
Reputation: 182819
You delete
the nodes you add to the list in both AddTail
and AddHead
. This leaves pointers to garbage in the list.
Also, it's not clear how to use your linked list. You cannot call AddHead
if head
is nullptr
(because AddHead
dereferences head
) and you cannot call AddTail
if tail
is nullptr
. Since your constructor sets both head
and tail
equal to nullptr
, what can you do next?
If it's legal for head
to be nullptr
, why does AddHead
do head->prev = tempRef;
without checking if head
is nullptr
?
I would strongly urge you to document your code. For example, what are the required preconditions for AddHead
to be called? Is it supposed to be safe to call if head
is nullptr
or is it a requirement that it not be? Why is that not documented?
Upvotes: 0