I am working on a doubly linked list assignment for my class and I am getting a segmentation fault on my test for the copy constructor. I don't know if the problem lies within my copyList method or my copy constructor logic. Any assistance be great.

Here is my header file and link to the assignment.

http://turing.cs.niu.edu/~t90kjm1/CS340/Assign/as01340f09.html

```
#ifndef LIST_H
#define LIST_H
#include <iostream>
template <class T>
class List;
template <class T>
std::ostream& operator<<(std::ostream&, const List<T>&);
template <class T>
struct LNode
{
T data;
LNode<T>* prev;
LNode<T>* next;
LNode(const T&);
};
template <class T>
LNode<T>::LNode(const T& newdata)
{
data = newdata;
prev = next = NULL;
}
template <class T>
class List
{
friend std::ostream& operator<< <>(std::ostream&, const List<T>&);
private:
LNode<T>* head;
LNode<T>* tail;
public:
List();
~List();
List(const List<T>&);
LNode<T>* copyList(LNode<T>*);
List<T>& operator=(const List<T>&);
void clear();
int size() const;
bool empty() const;
const T& front() const;
T& front();
const T& back() const;
T& back();
void push_front(const T&);
void push_back(const T&);
void pop_front();
void pop_back();
bool operator==(const List<T>&) const;
bool operator<(const List<T>&) const;
};
template <class T>
List<T>::List()
{
head = NULL;
tail = NULL;
}
template <class T>
List<T>::~List()
{
clear();
}
template <class T>
List<T>::List(const List<T>& oldList)
{
head = copyList(oldList.head);
tail = copyList(oldList.tail);
}
template <class T>
LNode<T>* List<T>::copyList(LNode<T>* ptr)
{
LNode<T>* newNode;
if(ptr==NULL)
return NULL;
else
{
newNode = new LNode<T>(ptr->data);
newNode->prev = copyList(ptr->prev);
newNode->next = copyList(ptr->next);
}
return newNode;
}
template <class T>
List<T>& List<T>::operator=(const List<T>& rightOp)
{
if (this != &rightOp)
{
clear();
head = copyList(rightOp.head);
tail = copyList(rightOp.tail);
}
return *this;
}
template <class T>
void List<T>::clear()
{
while(!empty())
pop_front();
}
template <class T>
int List<T>::size() const
{
LNode<T>* ptr = head;
int count = 0;
while(ptr != NULL)
{
count++;
ptr = ptr->next;
}
return count;
}
template <class T>
bool List<T>::empty() const
{
if(head == NULL or tail == NULL)
return true;
else
return false;
}
template <class T>
const T& List<T>::front() const
{
return head->data;
}
template <class T>
T& List<T>::front()
{
return head->data;
}
template <class T>
const T& List<T>::back() const
{
return tail->data;
}
template <class T>
T& List<T>::back()
{
return tail->data;
}
template <class T>
void List<T>::push_front(const T& item)
{
LNode<T>* newNode;
if(!empty())
{
newNode->prev = NULL;
newNode->next = head;
head->prev = newNode;
head = newNode;
}
else
{
newNode->prev = NULL;
newNode->next = head;
tail = newNode;
head = newNode;
}
}
template <class T>
void List<T>::push_back(const T& item)
{
LNode<T>* newNode;
newNode = new LNode<T>(item);
newNode->next = NULL;
newNode->prev = tail;
if(empty())
head = newNode;
else
tail->next = newNode;
tail = newNode;
}
template <class T>
void List<T>::pop_front()
{
if(size() > 1)
{
LNode<T>* delNode = head;
head = delNode->next;
head->prev = NULL;
delete delNode;
}
if(size() == 1)
{
LNode<T>* delNode = head;
head = delNode->next;
tail = NULL;
delete delNode;
}
}
template <class T>
void List<T>::pop_back()
{
if(size() > 1)
{
LNode<T>* delNode = tail;
tail = delNode->prev;
tail->next = NULL;
delete delNode;
}
if(size() == 1)
{
LNode<T>* delNode = tail;
tail = delNode->prev;
head = NULL;
delete delNode;
}
}
template <class T>
bool List<T>::operator==(const List<T>& rightOp) const
{
LNode<T>* p1;
LNode<T>* p2;
while(p1 != NULL and p2 != NULL)
{
if(p1->data != p2->data)
return false;
}
if(p1 == NULL and p2 == NULL)
return true;
else
return false;
}
template <class T>
bool List<T>::operator<(const List<T>& rightOp) const
{
LNode<T>* p1;
LNode<T>* p2;
while(p1 != NULL and p2 != NULL)
{
if(p1->data < p2->data)
return true;
if(p1->data > p2->data)
return false;
}
if(p2 == NULL)
return false;
else
return true;
}
template <class T>
std::ostream& operator<<(std::ostream& leftOp, const List<T>& rightOp)
{
LNode<T>* current;
for (current=rightOp.head; current != NULL; current = current->next)
std::cout << current->data << " ";
return leftOp;
}
#endif /*LIST_H*/
```