0

I have implemented a List (different from standard c++ list), this is for exercise. The problema is that after resizing the list, I get segmentation fault. I have marked the linke when I get seg. fault, I don't know the reason.

The purpose of resize method is to resize the list: let's say that I have a list of 2 integers, if I resize it to 5 I'll get other 3 elements, all initialized to zero. If instead I have a list of 4 elements, and I resize it to 2, 2 elelements will be cut. If I have a int list l, l[0] is the first object of the list, l[1] the second... So I crash when i attempt to resize the list, exactly in the line that I have marked.

#include <iostream>
#include <cassert>

using namespace std;

template<class T>
class List
{
public:
    List<T>();
    ~List<T>();
protected:
    List<T> (T info);
public:
    int size();
    void resize(int length);
    void add(T info,int i);
    void push(T info);
    T pop();
    void remove(int i);
    T extract(int i);
    T get(int i);
    friend ostream& operator<< (ostream& out, List<T>& l)
    {
        List<T>* ptr=l.next;
        if(l.info==NULL)
        {
            while(ptr!=&l)
            {
                out << *(ptr->info) << "\t";
                ptr=ptr->next;
            }
        }
        else
        {
            out<< *(l.info) <<"\t";
        }
        return out;
    }
    friend istream& operator>> (istream& in,List<T>& l)
    {
        in >> (*l.info);
        return in;
    }
    bool operator== (List<T>& r)
    {
        bool result=true;
        List<T>* p1,*p2;
        p1=this;
        p2=&r;
        assert((p1->info==NULL && p2->info==NULL)||(p1->info!=NULL && p2->info!=NULL));
        if(p1->info==NULL)
        {
            p1=p1->next;
            p2=p2->next;
            result=(p1->length == p2->length);
            while(result && p1!=this)
            {
                result=(*(p1->info)==*(p2->info));
                p1=p1->next;
                p2=p2->next;
            }
        }
        else
        {
            result=(*(p1->info)==*(p2->info));
        }
        return result;
    }
    List<T>& operator+= (List<T>& l)
    {
        List<T>* ptr;
        ptr=l.next;
        while(ptr!=&l)
        {
            this->push(*(ptr->info));
            ptr=ptr->next;
        }
        return *this;
    }
    List<T>& operator[] (int i)
    {
        List<T>* ptr;
        ptr=this;
        assert(i<length);
        for(int j=0;j<=i;j++)
            ptr=ptr->next;
        return *ptr;
    }
private:
    T *info;
    List <T>* next;
    List <T>* prev;
    int length;
};

template <class T>
List<T>::List ()
{
    info=NULL;
    next=this;
    prev=this;
    length=0;
}

template<class T>
List<T>::List (T info)
{
    next=this;
    prev=this;
    this->info=new T();
    *(this->info)=info;
}

template<class T>
List<T>::~List()
{
    List<T>* ptr, * temp;
    ptr=this->next;
    if(this->info==NULL)
    {
        while(ptr!=this)
        {
            delete ptr->info;
            temp=ptr;
            ptr=ptr->next;
            delete temp;
        }
    }
}

template<class T>
int List<T>::size()
{
    return length;
}

template<class T>
void List<T>::resize(int length)
{
    assert(length>=0);
    if(this->length<length)
    {
        for(int i=this->length;i<length;i++)
            push(0); 
    }
    else
    {
        for(int i=length;i<this->length;i++)
            extract(this->length-1); // here I call exctract, extract calls
    }                                // remove, remove calls get
}

template<class T>
void List<T>::add(T info,int i)
{
    List<T>* ptr,*t1,*t2;
    length++;
    ptr=&((*this)[i]);
    t1=ptr->prev;
    t2=ptr;
    ptr=new List<T>(info);
    t1->next=ptr;
    ptr->prev=t1;
    t2->prev=ptr;
    ptr->next=t2;
}

template<class T>
void List<T>::push(T info)
{
    add(info,length-1);
}

template<class T>
void List<T>::remove(int i)
{
    List<T>* ptr,*t1,*t2;
    ptr=&((*this)[i]);
    t1=ptr->prev;
    t2=ptr->next;
    delete ptr;
    t1->next=t2;
    t2->prev=t1;
    length--;
}

template<class T>
T List<T>::extract(int i)
{
    T temp=this->get(i);
    remove(i);
    return temp;
}

template<class T>
T List<T>::get(int i)
{
    assert(i<length);
    return *(this[i].info);         // here i have seg. fault !!!!!!!!!!
}                                   // I cannot figure why ...

template<class T>
T List<T>::pop()
{
    return extract(length-1);
}

int main(int argc, char **argv) 
{
    List<int> l;
    l.resize(3);
    for(int i=0;i<3;i++)
        cin>>l[i];
    l.resize(2);
    cout<<l<<endl;
    return 0;
}

I hope it's not a too kilometric doce, thanks in advance for who will read and try to help me.

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Ramy Al Zuhouri
  • 21,580
  • 26
  • 105
  • 187

1 Answers1

1

In resize, the for loops change i and compare it with this->length, but both push and extract change this->length, so you're comparing two changing variables against each other.

This may be better a better approach:

while(this->length < length)
    push(0); 
MRAB
  • 20,356
  • 6
  • 40
  • 33
  • I changed the code,but I think that the problem is when resizing the list to a smaller one: I still get seg. fault – Ramy Al Zuhouri Jan 26 '12 at 22:33
  • 1
    Is incredibile how a "*" can change everything in c++, I changed that line to "return *((*this)[i].info);" , indeed this is an address, now a value, so this[i] doesn't exist, I overloaded [] operator for an object, not for a reference.And yes, I will make a copy constructor and overload the assignment operator, thanks to who replied. – Ramy Al Zuhouri Jan 27 '12 at 00:05