0

So i am coding a browser tab structure, and i have 5 custom class, Stack, LinkedList, Node(for linked list), Tab and Browser. LinkedList and Stack works fine on their own, but when i construct a LinkedList in Browser's constructer i get error. So in my main i only call Browser().Here are the codes:

LinkedList<T>::LinkedList(){
  front=NULL;
  back=NULL;
}`

Node<T>::Node(){
    prev=NULL;
    next=NULL;
    data=T();
}

Stack<T>::Stack(int capacity){ //capacity is optional, this is the default constructor.
      this->capacity=capacity;
      this->size=0;
      this->items=new T[capacity];
}

`

Browser(){
            selected = NULL;
            //print browser link construction starts
            pages= LinkedList<Tab>(); //This line gives the error.
            closedPages= Stack<Tab>();
            curr_index=-1;
            tab_count=0;
}

Tab(){
    current_page="";
    prevPages=Stack<string>();
    nextPages=Stack<string>();
    closed_index=-1;
}

What is even funnier is that when i do print insertion, what i see is it first starts and finishes a link construction(without doing any tab construction in between), then does bunch of stack and tab construction, THEN prints the "browser link construction starts" and then goes in to and finishes another link construction and then gives seg fault. So it goes in to link construction twice even tough i hoped it would do only once?

Thanks, and sorry in advance if it is something extremly easy/stupid.

EDIT1: Full LinkedList Code

#ifndef _LINKEDLIST_H_
#define _LINKEDLIST_H_

#include <iostream>
#include <cstddef>
#include <stdexcept>
#include "Node.hpp"

using namespace std;

template <class T> 
class LinkedList {
    private:
        /* pointer to the first node */
        Node<T>* front;
        /* pointer to the last node */
        Node<T>* back;

    public:

        LinkedList();
        LinkedList(const LinkedList<T>& ll);
        LinkedList<T>& operator=(const LinkedList<T>& ll);
        ~LinkedList();

        /* returns the first node of the linked list */
        Node<T>& getFront() const;
        /* returns the last node of the linked list */
        Node<T>& getBack() const;
        /* returns the node in given "pos"ition of the linked list */
        Node<T>& getNodeAt(int pos) const;
        /* returns the pointer of the node in given 
           "pos"ition of the linked list */
        Node<T>* getNodePtrAt(int pos) const;

        /* inserts a new node containing "data" 
           after the node "prev" 
           */
        void insert(Node<T>* prev, const T& data);
        /* inserts a new node containing "data" 
           at "pos"ition in the linked list 
           */
        void insertAt(int pos, const T& data);
        /* erases the given "node" from the linked list */
        void erase(Node<T>* node);
        /* erases the node in given "pos"ition from the linked list */
        void eraseFrom(int pos);
        /* clears the contents of the linked list */
        void clear();

        /* inserts a new node containing "data" 
           to the front of the linked list 
           */
        void pushFront(const T& data);
        /* inserts a new node containing "data" 
           to the back of the linked list
           */
        void pushBack(const T& data);

        /* removes the first node */
        void popFront();
        /* removes the last node */
        void popBack();

        /* returns true if the list is empty, false otherwise */
        bool isEmpty() const;
        /* returns the number of items in the list */
        size_t getSize() const;
        /* prints the contents of the linked list 
           one node data per line
           assumes the objects in the node have operator<< overloaded 
           */
        void print() const;

};


template <class T>
LinkedList<T>::LinkedList(){
  cout << "list construction starts" << endl;
  front=NULL;
  back=NULL;
  cout << "list construction ends" << endl;
}

//COPY AND ASSIGMENT
template<class T>
LinkedList<T>::LinkedList(const LinkedList<T>& ll){
  *this=ll;
}
template<class T>
LinkedList<T>&  LinkedList<T>::operator=(const LinkedList<T>& ll){
  clear();
  Node<T>* temp=&(ll.getFront());
  while(temp->getNext()!=NULL){
    pushBack(temp->getData());
    temp->setNext(temp->getNext());
  }
  pushBack(temp->getData());
  return *this;
}
template<class T>
LinkedList<T>::~LinkedList(){
  clear();
}

template <class T>
Node<T>& LinkedList<T>::getFront() const{
  return *front;
}
template <class T>
Node<T>& LinkedList<T>::getBack() const{
  return *back;
}
template <class T>
Node<T>& LinkedList<T>::getNodeAt(int pos) const{
  if(pos<0 or pos>=getSize()){
    throw out_of_range("Bad Input");
  }  
  Node<T>* retval=front;
  for(int i=0;i<pos;i++){
        retval=retval->getNext();
  }
  return *retval;
}
template <class T>
Node<T>* LinkedList<T>::getNodePtrAt(int pos) const{
  if(pos<0 or pos>getSize()){
    throw out_of_range("Bad Input");
  }
  Node<T>* retval=front;
  for(int i=0;i<pos;i++){
        retval=retval->getNext();
  }
  return retval;
}

template <class T>
void LinkedList<T>::insert(Node<T>* prev,const T& data){
  if(prev==NULL){
    pushFront(data);
  }
  else if(prev==back){
    pushBack(data);
  }
  else{
    Node<T>* newNode=new Node<T>();
    newNode->setData(data);
    prev->getNext()->setPrev(newNode);
    newNode->setNext(prev->getNext());
    newNode->setPrev(prev);
    prev->setNext(newNode);
    }
}
template <class T>
void LinkedList<T>::insertAt(int pos,const T& data){
  if(pos==0){
    pushFront(data);
  }
  else if(pos==getSize()){
    pushBack(data);
  }
  else{
    Node<T>* tmp=getNodePtrAt(pos);
    Node<T> newNode;
    newNode.setData(data);
    tmp->getPrev()->setNext(&newNode);
    newNode.setNext(tmp);
    newNode.setPrev(tmp->getPrev());
    tmp->setPrev(&newNode);
  }

}


template <class T>
void LinkedList<T>::pushFront(const T& data){
  Node<T>* newNode=new Node<T>();
  newNode->setData(data);
  if(front==NULL){
    front=newNode;
    back=newNode;
  }
  else {
    newNode->setNext(front);
    front->setPrev(newNode);
    front=newNode;
    newNode->setPrev(NULL);
  }
}

template <class T>
void LinkedList<T>::pushBack(const T& data){
  Node<T>* newNode=new Node<T>();
  newNode->setData(data);
  if(front==NULL){
    front=newNode;
    back=newNode;
  }
  else {
    newNode->setPrev(back);
    back->setNext(newNode);
    back=newNode;
    newNode->setNext(NULL);
  }

}

template <class T>
void LinkedList<T>::erase(Node<T>* node){
  if(node==front){
    popFront();
  }
  if(node==back){
    popBack();
  }
  else {
    node->getNext()->setPrev(node->getPrev());
    node->getPrev()->setNext(node->getNext());
    node->setNext(NULL); node->setPrev(NULL);
  }
  delete node;

}
template <class T>
void LinkedList<T>::eraseFrom(int pos){
Node<T>* tmp=getNodePtrAt(pos);
erase(tmp);
}
template <class T>
void LinkedList<T>::clear(){
  while(!isEmpty()){
    popFront();
  }
}


template <class T>
void LinkedList<T>::popFront(){
  Node<T>* tmp;
  tmp=front;
  if(front==back){
    front=NULL;
    back=NULL;
  }
  else{
    front=front->getNext();
    front->setPrev(NULL);
  }
  delete tmp;
}
template <class T>
void LinkedList<T>::popBack(){
  Node<T>* tmp;
  tmp=back;
  if(front==back){
    front=NULL;
    back=NULL;
  }
  else {
    back=back->getPrev();
    back->setNext(NULL);
  }
  delete tmp;
}

template <class T>
bool LinkedList<T>::isEmpty() const{
  return front==NULL;
}
template <class T>
size_t LinkedList<T>::getSize() const{
  if(front==NULL){
    return 0;
  }
  size_t size=1;
  Node<T>* current=front;
  while(current->getNext()!=NULL){
    size++;
    current=current->getNext();
  }
  return size;
}

template <class T>
void LinkedList<T>::print() const{
  Node<T>* current=front;
  if(front!=NULL){
    while(current->getNext()!=NULL){
        cout << current->getData() << endl;
        current=current->getNext();
    }
    cout << current->getData() << endl;
  }
}

#endif
Deniz Uluğ
  • 95
  • 1
  • 1
  • 6

1 Answers1

3

Your assignment operator appears to be problematic. In your Browser constructor I see this:

pages = LinkedList<Tab>();

This is actually unnecessary but is triggering your problem. Your 'pages' variable is already default constructed (which is why you see all that activity before the print statement) by the time your Browser constructor code begins. Then you perform the assignment which utilizes your assignment operator.

Your assignment operator is assuming that the source LinkedList object has data, but it does not. It is calling getFront() which dereferences 'front', which is NULL. You should check if it is empty first, which I see you have a method for already (isEmpty()).

Nicholas Smith
  • 975
  • 7
  • 18
  • Long story short, `operator=` has multiple problems. – Robert Prévost Nov 17 '16 at 01:07
  • Thanks i guess, i still couldn't comprehend it fully but right now i deleted that line and keep debugging, i hope it will work. But the case is in private members i have: LinkedList pages;Stack closedPages; And i tough in constructor i would implement them, so what i get is i dont have to? – Deniz Uluğ Nov 17 '16 at 01:08
  • Class members which are C++ objects (such as the ones you mentioned) are automatically constructed using their default constructor and so you do not need to assign them any value like you have done in the provided code. You really only need to initialize the values for class members which are not C++ objects (primitives such as ints, pointers, booleans, etc). Also, the initialization can be (and is typically) done in the constructor initializer list (decent reference: http://stackoverflow.com/questions/926752/why-should-i-prefer-to-use-member-initialization-list) – Nicholas Smith Nov 17 '16 at 18:35