calvin11
calvin11

Reputation: 187

Problems with copying an array into another dynamic array

I have a problem with the execution of this program. I do not know why it ends up running so abruptly ("The program stopped working"). The results of it are what I hope, however that happens. And I tried many things to avoid it and found that what causes the error is the function void IntArr::addElement(int qtty,int *vec); since if I remove it, the program finishes perfectly and without any error. Analyze the function and for me it's fine, I do not know what is slipping from my hands. The function that what you should do is pass an array with the amount of elements that I want from it and add them to another array.

PS: the original program was well divided by files (class.h, class.cpp, main.cpp), nothing more than to copy them here I had to paste everything together.

I would appreciate your help. Regards!

#include <iostream>
using std::cout;
using std::endl;
#define PRESS_KEY std::cout<<"\nPresione Enter para continuar . . .\n";std::cin.get();

class IntArr{
  private:
    int * p;
    int size;
    int used;
    //Verificador
    void redimensionador(int cant);

  public:
    //Constructores
    IntArr (int sz);
    IntArr (int sz,int qtty,int *vec);
    //Destructor
    ~IntArr();
    //Visualizadores
    void prtArr (void) const;
    void prtArr (int cant);
    //Accesores
    int getSize(){return size;};
    int getUsed(){return used;};
    //Operaciones
    void addElement(int xx);
    void addElement(int qtty,int *vec);
};
//Constructores
IntArr::IntArr(int sz){
  size = sz;
  used = 0;
  p = new int[size];
}
IntArr::IntArr(int sz,int qtty,int* vec){
  if(qtty>sz){
    sz = qtty;
  }
  size = sz;
  used = qtty;
  p = new int[size];
  p = vec;
}

//Destructor
IntArr::~IntArr(){
  delete []p;
}

//Visualizadores
void IntArr::prtArr(void) const{
  if(used == 0){
    cout<<endl<<"El array no tiene elementos."<<endl;
  }
  else{
    cout<<endl<<"Array: ";
    for(int i=0;i<used;i++){
      cout<<p[i]<<", ";
    }
    cout<<endl;
  }
}
void IntArr::prtArr(int cant){
  if(used == 0){
    cout<<endl<<"El array no tiene elementos."<<endl;
  }
  else{
    cout<<endl<<"Array: ";
    for(int i=0;i<cant;i++){
      cout<<p[i]<<", ";
    }
    cout<<endl;
  }
}

//Operaciones
double IntArr::getAvg(){
  double acum = 0;
  for(int i=0;i<used;i++){
    acum += p[i];
  }
  return (acum/used);
}
void IntArr::addElement(int xx){
  redimensionador(1);
  p[used] = xx;
  used++;
}
void IntArr::addElement(int qtty,int *vec){
  int j=0;
  redimensionador(qtty);
  for(int i=used;i<(used+qtty);i++){
    p[i] = vec[j];
    j++;
  }
  used += qtty;
}

//Verificador
void IntArr::redimensionador(int cant){
  if(cant+used>size){
    if(cant > 5){
      size += cant;
    }
    else{
      size += 5 + cant;
    }
  }
}

int main(int argc, char *argv[]){
  int v_aux[]= {0,5,10,15,20,25,30,35,40};
  IntArr A(10,sizeof(v_aux)/sizeof(int),v_aux);
  cout<<" size:"<<A.getSize()<<endl<<" used:"<<A.getUsed()<<endl;
  A.prtArr();
  A.addElement(77);
  cout<<" size:"<<A.getSize()<<endl<<" used:"<<A.getUsed()<<endl;
  A.prtArr();
  A.addElement(11);
  cout<<" size:"<<A.getSize()<<endl<<" used:"<<A.getUsed()<<endl;
  A.prtArr();
  A.addElement(8,v_aux);
  cout<<" size:"<<A.getSize()<<endl<<" used:"<<A.getUsed()<<endl;
  A.prtArr();
  PRESS_KEY;
}

Upvotes: 0

Views: 144

Answers (3)

R Sahu
R Sahu

Reputation: 206607

One problem I noticed is in the following lines:

p = new int[size];
p = vec;

When you do that:

  1. You have a memory leak. The value returned by new int[size] is lost to your program.
  2. You point p to the statically defined array in main. That leads to undefined behavior when you use delete [] p; in the destructor.

I am guessing you want to copy the values from vec to p. You'll have to copy the values one by one.

The manually coded version for that:

for (int i = 0; i < used; ++i )
{
   p[i] = vec[i];
}

Using the standard library function std::copy:

std::copy(vec, vec+used, p);

Upvotes: 2

Vlad from Moscow
Vlad from Moscow

Reputation: 310990

Even this constructor has a memory leak and can result in undefined behaviour (for example when vec points to first element of a local array or when the array poined by the argument vec will be deleted).

IntArr::IntArr(int sz,int qtty,int* vec){
  if(qtty>sz){
    sz = qtty;
  }
  size = sz;
  used = qtty;
  p = new int[size];
  p = vec;
}

At first a memory is allocated and its address is assigned to p and then p is reassigned.

  p = new int[size];
  p = vec;

You have to copy elements from the array pointed to by the argument vec into the allocated memory pointed to by the data member p.

And this member function

void IntArr::redimensionador(int cant){
  if(cant+used>size){
    if(cant > 5){
      size += cant;
    }
    else{
      size += 5 + cant;
    }
  }
}

does not make sense. You have to reallocate the original array pointed to by the data member p.

Upvotes: 1

Chris Uzdavinis
Chris Uzdavinis

Reputation: 6131

If you run out of memory, you can not just say you have more size by adding to an integer. You have to reallocate the memory, copy the values from the old array into the new array, then delete the old array.

You also need to be careful here. Raw pointers are error prone, and I see you have some strange constructs here. For example, IntArr::IntArr(int sz,int qtty,int* vec) you allocate a pointer, then immediately overwrite it. That allocation is a leak.

Be sure you properly update size and used so that you don't lose track of how much memory you actually have. When size changes, so must your buffer or you are out of sync.

Upvotes: 1

Related Questions