Copy constructor throws a std::bad_alloc, when it is called - c++

I am new c++ programmer. I want to create a Matrix class in c++ using dynamic programming. I had a problem with copy constructor. When I call operator + to use it for matrix-addition, the copy constructor throws a bad_alloc-Exception. The problem occurs in the copy-constructor, when i try to create a new dynamic memory, where i can copy my data:
matrix= new int [size];
I don 't understand why.
Here is the whole code: (only the cpp-file)
#include <iostream>
#include "Matrix.hpp"
Matrix::Matrix(int m, int n){
mat_row=m;
mat_col=n;
matrix = new int[mat_row*mat_col];
//initialization
for(int i=0;i<mat_row*mat_col;i++){
matrix[i]=0;
}
}
//copy-Constructor
Matrix::Matrix(const Matrix& mat){
int size=mat_row*mat_col;
matrix= new int [size];
for(int i=0;i<size;i++){
matrix[i]=mat.matrix[i];
}
}
Matrix::~Matrix(){
if(matrix){
delete [] matrix;
}
}
//assigment operator
Matrix& Matrix::operator=(const Matrix& mat){
std::cout<<"assignment-operator is used"<<std::endl;
if(this!=&mat){
int size=mat_row*mat_col;
for(int i=0;i<size;i++){
matrix[i]=mat.matrix[i];
}
}
return *this;
}
void Matrix::set(int m, int n, double value){
if(matrix){
matrix[m*mat_col+n]=value;
}
}
double Matrix::get(int m, int n){
return matrix[m*mat_col+n];
}
Matrix Matrix::operator+(Matrix mat){
/*
Matrix resultMatrix(mat_row, mat_col);
for(int i=0;i<mat_row;i++){
for( int j=0;j<mat_col;j++){
resultMatrix->set(i,j,this->get(i,j)+mat.get(i,j));
}
}
return *this;
*/
}
int main(){
Matrix mat1(3,3);
mat1.set(0,0,11);
mat1.set(1,1,22);
mat1.set(2,2,33);
mat1.print();
std::cout<<std::endl;
Matrix mat2(3,3);
mat2=mat1;
mat2.print();
std::cout<<std::endl;
mat2.set(0,1,55);
mat2.set(1,1,110);
mat2.set(2,2,220);
mat2.print();
mat1+mat2; //the problem occurs when this row will be executed
}

The first thing I noticed is that in your copy constructor mat_row and mat_col are not initialized. They should be getting set from the values that are in the object you are copying before you multiply them together to make size. If you don't do that first then the existing values are undefined and likely very large values, causing the new to fail.
//copy-Constructor
Matrix::Matrix(const Matrix& mat){
mat_row = mat.mat_row;
mat_col = mat.mat_col;
int size=mat_row*mat_col;
matrix= new int [size];
for(int i=0;i<size;i++){
matrix[i]=mat.matrix[i];
}
}
It looks like you have the exact same problem in you operator=() as well.
In the code where you indicate that your problem shows up you do not have an lvalue. You have mat1+mat2; so the result of that addition ends up being unused.
Also, your operator+() should be taking a const ref to the matrix and that is your actual issue. Passing by value like you currently are will cause a temporary copy which is created through the copy constructor.

Related

Core Dumped due to delting an array

I'm trying to make a copy constructor with low level arrays and I'm getting a core dumped error when using delete, can't find out a solution because I'm not able to use std::vector to make this.
Can you guys help me ?? =)
#include<iostream>
#include<string>
#include<initializer_list>
class Vector{
size_t n;
double* datos;
public:
Vector(size_t n_,double);
Vector(const std::initializer_list<double>&l);
void show();
~Vector(){
delete[] datos;
}
Vector(Vector&& other):n(other.n){
delete [] datos;
datos =other.datos;
other.datos =nullptr;
}
Vector(const Vector& v);
Vector operator = (const Vector& v);
};
/* --------------------------- METODOS DE LA CLASE -------------------------- */
Vector::Vector(const Vector&v){
delete[]datos; //CORE DUMPED
n=v.n;
datos = new double[n];
for (size_t i = 0; i < n; i++)
{
datos[i] = v.datos[i];
}
std::cout<<std::endl;
}
Vector Vector::operator = (const Vector& v){
delete [] datos;//CORE DUMPED
n = v.n;
for (size_t i = 0; i < n; i++)
{
datos[i] = v.datos[i];
}
return *this;
}
Vector::Vector(const std::initializer_list<double>&l):n(l.size()),datos(new double[n]){
size_t j= 0;
for (auto i:l)
{
datos[j]=i;
++j;
}
}
void Vector::show(){
for (size_t i = 0; i < n; i++)
{
std::cout<<datos[i]<<", ";
}
std::cout<<std::endl;
}
Vector::Vector(size_t n_,double d=0):n(n_),datos(new double[n]){
if (n < 1)
{
throw std::invalid_argument("Wrong size!");
}
for (size_t i = 0; i < n; i++)
{
datos[i] = d;
}
}
int main(){
Vector b={2,3,4,5,6},a(3);
a=b;
a.show();
}
Using POP OS 21.04 (just in case this can help).
Please don't be rough with me I'm a junior programmer trying to pass September's exams =(
Vector::Vector(const Vector&v){
delete[]datos; //CORE DUMPED
You didn't initialise datos, so its value is indeterminate. When you delete an indeterminate pointer, then the behaviour of the program is undefined. "CORE DUMPED" is one possible behaviour that you may observe.
You are issuing unneeded calls to delete [] datos in your constructors (move and copy).
Since datos is uninitialized, calling delete [] on an uninitialized pointer leads to undefined behavior -- in your case, your program crashes.
Since the objects are being constructed, there is no reason to issue a delete [] on the pointer, since the object this is brand new.
Simply remove the call to delete [] datos; from the constructors. Whether this is the only problem is another story, but it is an existing one.
In addition, your assignment operator:
Vector Vector::operator = (const Vector& v)
is also incorrect. It fails to allocate new memory after the delete [] call, thus the for loop that is written will write into unallocated memory. Also, it should return a reference to the current Vector object, not a brand new Vector object.
The easiest way to implement the assignment operator is to use std::swap:
#include <algorithm>
//...
Vector& Vector::operator = (Vector v)
{
std::swap(v.datos, datos);
std::swap(v.n, n);
return *this;
}
This assumes you have a working, non-buggy copy constructor and destructor for Vector. See the copy / swap idiom for details on why this works.

Going through array using for_each loop in cpp

First off, here is the code:
#include <iostream>
#include <algorithm>
using namespace std;
class Array
{
int* arr;
int n;
public:
Array();
Array(const Array&);
Array(Array &&);
Array& operator=(const Array&);
Array& operator=(Array &&);
void print();
~Array();
};
Array::Array()
{
cout<<"No of elements: "<<endl;
cin>>n;
if(n!=0)
{
arr = new int [n];
cout<<"\nInsert values:"<<endl;
for_each(arr, arr+n, [](int x){cin>>x;});
}
}
Array::Array (const Array& a)
{
int i=0;
this->n=a.n;
arr= new int [n];
for(i=0;i<n;i++)
arr[i]=a.arr[i];
}
Array::Array (Array &&a)
{
this->n=a.n;
arr=a.arr;
a.arr=nullptr;
}
Array& Array::operator=(const Array& a)
{
int i=0;
this->n=a.n;
arr= new int [n];
for(i=0;i<n;i++)
arr[i]=a.arr[i];
return *this;
}
Array& Array::operator=(Array &&a)
{
this->n=a.n;
arr=a.arr;
a.arr=nullptr;
return *this;
}
void Array::print()
{
for_each(arr, arr+n, [](int a){cout<<a;});
}
Array::~Array()
{
n=0;
delete [] arr;
}
int main()
{
Array a;
Array b;
Array c=a;
Array d;
d=b;
c.print();
cout<<endl;
d.print();
return 0;
}
So, as you can see, i made default constructor (if constructor with no parameters can be called default) that creates an array using for_each loop with lambda function used as a third parameter, all it does, as you can see is that it accepts the values i insert and places it as a values of variable x, which should take values from arr[0] to arr[n-1].
However, when i print put any of arrays created in main, it prints out only zeroes, it is not due to copy constructors, because i tried printing arrays a and b and same thing happened (notice that in this case i am printing out c and d, as they are copies of a and b, respectively).
I also tried to see if it works properly as i tried to print out some elements of array right after for_each loop finished, and it turns out that for_each loop has no effect on the array as it stays zero even right after loop.
Any help appreciated!
When you're using for_each loops, you're passing a lambda,
for_each(arr, arr+n, [](int x){cin>>x;});
But the argument of the lambda (int x), mean that you're creating a copy of an array element, that you will assign a value to. That copy will be destroyed when you leave the body of the lambda, while the original value inside the array remains unchanged.
Change it to
for_each(arr, arr+n, [](int& x){cin>>x;});
That way you won't create a copy of the value inside the array, but you'll pass a reference to it, which means you will write the values into the array.

the way of writing constructor, deconstructor and copy constructor for matrix class

I am trying to create a constructor, destructor, and copy constructor for a matrix class, and I am not so sure if I am doing it well.
In particular, I am not sure about 2 things:
Is the destructor suppose to free memory also for the memory that is allocated in the copy-constructor?
As to the line Mat[i][j]=other[i][j] (see in the code below), I wonder if I should write Mat[i][j]=other.Mat[i][j] instead?
class Matrix
{
private:
int rows;
int cols;
int **Mat;
public:
Matrix (const int &rows,const int &cols);
Matrix (const Matrix &other);
~Matrix ();
};
Matrix::Matrix(const int &n_rows,const int &n_cols) //constructor of class Matrix
{
rows=n_rows;
cols=n_cols;
Mat=new int* [cols];
for(int i =0;i<rows;i++)
Mat[i]=new int[cols];
for(int i=0;i<rows;i++)
for(int j=0;j<cols;j++)
Mat[i][j]=0;
}
Matrix::~Matrix () //destructor
{
for(int i =0;i<rows;i++)
delete Mat[i];
delete[] Mat;
}
Matrix::Matrix(const Matrix &other) //copy constructor
{
cols=other.cols;
rows=other.rows;
Mat=new int* [other.rows];
for(int i =0;i<other.rows;i++)
Mat[i]=new int[other.cols];
for(int i=0;i<other.rows;i++)
for(int j=0;j<other.cols;j++)
Mat[i][j]=other[i][j];
}
1) I think deconstructor erases only object that belongs to, because copy-constructed objects have their own destructor.
2) Yes, Mat[i][j] = other.Mat[i][j] is right, but if you want your program to be bit faster, try using pointers (it isn't easy at first time, I know, but when you get used to it isn't that hard ^^)
A constructor is a class operation that initializes an object instance of a specific class.
The object creation involves several operations such as:
Allocating memory to store the structure for the new object
Initializing the object's attributes properly.
A copy constructor is a special case of constructor, that takes an instance of the same class as an input parameter. - It is still a constructor, performing the same operations mentioned above.
A destructor is a class operation which is responsible for finalizing an object when it is not to be used anymore.
An object can be constructed using any constructor it defines, either ordinary or copy constructor. When you delete that object, any memory allocated by your class should be deallocated in the destructor.
Hope this helps.
As for your code related question; when invoking a copy constructor, you pass an existing object instance of the class. Since you don't have any operator overloading implemented, you access the object's property like you said in #2.
I am not sure if this answers your questions fully, but I hope it helps.
Yes. Anything the object still has allocated should be freed in the destructor. It doesn't matter which constructor allocated it.
Yes, you need to use Mat[i][j]=other.Mat[i][j], especially since you haven't defined any operator[] for your class.
You also need to add a copy assignment operator, per the "Rule of Three", which basically states:
If a class requires a user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, it almost certainly requires all three.
Try this:
class Matrix
{
private:
int rows;
int cols;
int **Mat;
public:
Matrix (int n_rows, int n_cols);
Matrix (const Matrix &other);
~Matrix ();
Matrix& operator=(const Matrix &rhs);
// alternatively:
// Matrix& operator=(Matrix rhs);
};
Matrix::Matrix(int n_rows, int n_cols)
{
rows = n _rows;
cols = n_cols;
Mat = new int*[rows];
for(int i = 0; i < rows; ++i)
{
Mat[i] = new int[cols];
for(int j = 0; i < cols; ++j)
Mat[i][j] = 0;
}
}
Matrix::Matrix(const Matrix &other)
{
rows = other.rows;
cols = other.cols;
Mat = new int*[rows];
for(int i = 0; i < rows; ++i)
{
Mat[i] = new int[cols];
for(int j = 0; j < cols; ++j)
Mat[i][j] = other.Mat[i][j];
}
}
Matrix::~Matrix()
{
for(int i = 0; i < rows; ++i)
delete Mat[i];
delete[] Mat;
}
Matrix& Matrix::operator=(const Matrix &rhs)
{
if (&rhs != this)
{
Matrix temp(rhs);
std::swap(Mat, temp.Mat);
std::swap(rows, temp.rows);
std::swap(cols, temp.cols);
}
return *this;
}
// alternatively:
/*
Matrix& Matrix::operator=(Matrix rhs)
{
std::swap(Mat, rhs.Mat);
std::swap(rows, rhs.rows);
std::swap(cols, rhs.cols);
return *this;
}
*/
A better solution is to not use new[]/delete[] directly at all. Use std::vector instead, and let it handle everything for you, thus allowing your class to follow the "Rule of Zero":
Classes that have custom destructors, copy/move constructors or copy/move assignment operators should deal exclusively with ownership (which follows from the Single Responsibility Principle). Other classes should not have custom destructors, copy/move constructors or copy/move assignment operators.
class Matrix
{
private:
std::vector<std:vector<int> > Mat;
public:
Matrix (int n_rows, int n_cols);
};
Matrix::Matrix(int n_rows, int n_cols)
{
Mat.resize(n_rows);
for(int i = 0; i < n_rows; ++i)
Mat[i].resize(n_cols, 0);
/* alternatively:
Mat.resize(n_rows, std::vector<int>(n_cols, 0));
*/
}

stable_sort on objects containing dynamic tables

I have a problem with sorting. I sort the objects containing the dynamic table. It seems that the stable_sort (or the vector) doesn't use a public copy constructor. I looks like they use a non-existent constructor with no parameter because the tables inside the objects are freed - I think.
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
class Dynamic{
int n;
int *tab;
public:
int getN() const{ return n;}
int *getTab() const {return tab;}
Dynamic(int ile){
n=ile;
tab=new int[n];
for(int i=0; i<n; i++)
tab[i] = (10-i)%10;
}
Dynamic(const Dynamic& d){
n = d.getN();
tab = new int[n];
for(int i=0; i<n; i++)
tab[i] = d.getTab()[i];
}
bool operator<(const Dynamic& a) const{
return n < a.getN();
}
~Dynamic(){
delete[] tab;
}
};
int test(vector<Dynamic> & c){
vector<Dynamic> d(c);
stable_sort(d.begin(), d.end());
d.clear();
}
int main(){
vector<Dynamic> c;
c.push_back(Dynamic(15));
test(c);
cout<<"test!";
return 0;
}
STL's sort is also affected but in slightly more complex way.
In g++-4.7.2 I can compile this and in running I get "double free or corruption (fasttop)"/core dumped (full report isn't helpful, I think). On online g++-4.9.0 it looks similar: "No output: Error: stdout maxBuffer exceeded.".
Where is my mistake? Thank you for your attention.
Well, you didn't overload the operator= for Dynamic, so the compiler implicitly defines one which would do bitwise copy. stable_sort() in your library calls the operator=, so tab in two Dynamic objects points to the same address, as a result, double delete on destruction. Overloading the operator= would resolve the problem:
Dynamic& operator =(const Dynamic& d)
{
// or use the copy-and-swap idiom
if(this != &d)
{
delete [] tab;
n = d.getN();
tab = new int[n];
for (int i = 0; i<n; i++)
tab[i] = d.getTab()[i];
}
return *this;
}

Following program is throwing an error related memory access

/This program is using template class. I don't know why but this program is throwing an error at run time related memory access violation. in below comments i will explain which line is causing this error./
#include<iostream>
using namespace std;
const int size =3;
template <class t="">
class vector
{
T* v;
public:
vector()
{
v=new T[size];
for(int i=0;i<size;i++)>
v[i]=0;
}
vector(T* a)
{
for(int i=0;i<size;i++)>
v[i]=a[i];
}
T operator*(vector &y)
{
T sum=0;
for(int i=0;i<size;i++)>
sum+=this->v[i] * y.v[i];
return sum;
}
void display(void)
{
for(int i=0;i<size;i++)>
{
cout<<v[i]<<"\t";
}
cout<<"\n";
}
};
int main()
{
int x[3]={1,2,3};
int y[3]={4,5,6};
vector<int> v1;
vector <int> v2;
v1=x; // This is causing an error
v2=y; // This is causing an error
//int R=v1*v2;
//cout<<"R = "<<R<<"\n";
cout<<"V1 = ";
v1.display();
cout<<"V2 = ";
v2.display();
cout<<"V1 x V2 = "<<v1*v2;
return 0;
}
It seems that the problem is in this constructor
vector(T* a)
{
for(int i=0;i<size;i++)>
v[i]=a[i];
}
You did not allocate memory for the array pointed by v.
2 Problems:
You are not initializing memory for your vector
You are calling the constructor incorrecly
To fix #1
vector(T* a)
{
v=new T[size];
for(int i=0;i<size;i++)>
v[i]=a[i];
}
To fix #2
int x[3]={1,2,3};
int y[3]={4,5,6};
vector<int> v1(x);
vector <int> v2(y);
the constructor vector(T * a) will get called and the member v is not initialized with anything. This causes undefined behavior. So to fix this you need to allocate in that constructor
vector(T* a)
{
v = new T[size];//this line is new
for(int i=0;i<size;i++)
v[i]=a[i];
}
My guess is there is no operator=(int []) defined for vector.
So in other words, compiler does not know what do you mean by v1=x when it comes to type int[] = vector<int>.
You are not calling the overloaded constructor there. So you either need to call it vector<int> v1(y); or implement vector::operator=(const T[] v);
I hope i got the types right
When calling the lines in question, the program is using a default assignment operator which is doing something that causes your violation. You need to implement this yourself, for example, this worked for me:
T& operator=(T const * a)
{
for(int i=0;i<size;i++)
v[i]=a[i];
return *this;
}