memory leak in overloading operator = - c++

I have this constructor for matrix to allocate memory
class Matrix
{
public:
int** matrix;
int cols;
int rows;
};
Matrix::Matrix(int row, int col)
{
cols = col;
rows = row;
matrix = new int*[rows];
int i;
for (i = 0; i < rows; ++i)
{
matrix[i] = new int[cols];
}
}
now I want to overload the operator =, but I can't figure out how to write the function and allocate the new memory, without getting a memory leak, or not having enough memory.
The matrix the I'll do the = on it, already has memory allocated for it, so can i delete the memory and make new memory on the size of the other one?
for now I have this on the operator =
this->rows = other.rows;
this->cols = other.cols;
int i, j;
for (i = 0; i < this->rows; ++i)
{
for (j = 0; j < this->cols; j++)
{
this->matrix[i][j] = other.matrix[i][j];
}
}
return *this;

The idiomatic way is to use the copy/swap idiom. See What is the copy-and-swap idiom?
The assignment is then reduced to
Matrix& operator=(Matrix copy){
swap(*this, copy);
return *this;
}
See the linked question for all the perks you gain by using this idiom.

I would recommend switching from manually allocating arrays to using std::vector
class Matrix
{
public:
Matrix(int row, int col);
int cols;
int rows;
std::vector<std::vector<int>> matrix;
};
Matrix::Matrix(int row, int col)
: cols(col),
rows(row),
matrix(rows, std::vector<int>(cols))
{ }
Now you can let the compiler generate your copy assignment operator, and the other constructors, destructor, etc. This class is now copyable, moveable, and doesn't leak memory because matrix now uses RAII semantics instead of you having to manage its memory.

First you can reallocate the each column using the delete operator.
for (i = 0; i < rows; ++i)
{
delete []matrix[i];
}
Then you can deallocate pointers to each row.
delete []matrix;
After that you can allocate the new matrix as required from the one passed as argument.

Related

Access violation when using delete[] on a 2-dim array [duplicate]

This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 2 years ago.
I'm doing a matrix-product exercise (strassen's algorithm actually) using C++. Since the biggest data set given reaches 2048 * 2048, I tried to free the temp memory using delete[]. But it says there is a memory access violation in it, why?
Here are some of the code that may help:
struct Matrix {
int row, column;
int** m;
Matrix(int row, int column) {
m = new int* [2048];
for (int i = 0; i < row; i++)
m[i] = new int[2048];
}
~Matrix() {
if (m != NULL) {
for (int i = 0; i < 2048; i++) {
delete[] m[i]; //access violation happens here
}
delete[] m;
}
}
};
Matrix matAdd(Matrix matA, Matrix matB) {
Matrix matR = Matrix(matA.row, matA.column);
for (int i = 0; i < matA.row; i++)
for (int j = 0; j < matA.column; j++) {
matR.m[i][j] = matA.m[i][j] + matB.m[i][j];
}
return matR;
}
//There are some other functions below but the structure is basically the same
The pointers in the array, starting from the index row were not initialized.
Matrix(int row, int column) {
m = new int* [2048];
for (int i = 0; i < row; i++)
m[i] = new int[2048];
// Initialize rest elements with null pointer.
for (int i = row; i < 2048; i++)
m[i] = nullptr;
}
The rest initialization will fix the crash, but then you will get crash on double free. The reason: you use copies of your class, thus you need to implement the copy constructor and the assignment operator or use shared pointers instead of raw pointers. The default copy makes pointers pointing to the same allocated objects.
Also look at the answer https://stackoverflow.com/a/1403180/6752050 with the example how to create a 2d matrix with a single allocation.
You should consider using std::vector<std::vector<int>>.
Your class is lacking copy constructor and copy assignment and I am certain it is a case of double free.

Assigning memory in C++

I am attempting to learn how to assign memory in C++. I followed this answer to allocating 2-D arrays: Copy 2D array using memcpy?
However, when I attempt to combine this and copying memory using std::copy I get a corruption.
#include <iostream>
class Matrix
{
private:
int nrows;
int mcols;
double **entry;
public:
Matrix(int n, int m);
~Matrix();
Matrix& operator=(const Matrix& mat_in);
};
Matrix::Matrix(int n, int m)
{
nrows = n;
mcols = m;
std::cout << "Using regular constructor" << std::endl;
entry = new double*[nrows];
entry[0] = new double[nrows * mcols];
for(int i=1;i<nrows;i++)
entry[i] = entry[i-1] + mcols;
for(int i=0;i<nrows;i++)
for(int j=0;j<mcols;j++)
entry[i][j] = 0.0;
}
Matrix::~Matrix()
{
delete[] entry[0];
delete[] entry;
}
Matrix& Matrix::operator=(const Matrix& mat_in)
{
std::cout << "using deep copy constructor" << std::endl;
if(this == &mat_in)
return *this;
double **p = new double*[mat_in.nrows];
p[0] = new double[mat_in.nrows * mat_in.mcols];
std::copy(mat_in.entry, mat_in.entry + (mat_in.nrows * mat_in.mcols), p);
delete[] this -> entry;
entry = p;
nrows = mat_in.nrows;
mcols = mat_in.mcols;
return *this;
}
int main()
{
Matrix A(3,3);
Matrix B(3,3);
B = A;
return 0;
}
I think the problem is that I don't fully understand what is happening when I free the memory and I am freeing it twice.
You're mixing the two basic kinds of 2-D array allocation.
In one style, one allocates an array (size nRows) of row pointers, and then allocates an array (size nCols) of elements for each row. Addressing an element is rows[r][c].
In the other style, one allocates an array (size nRows*nCols) of elements for the whole thing. Addressing an element is elements[(r * nCols) + c].
Your copy assignment operator is bugged (despite your comment it's not a copy constructor). Specifically this
std::copy(mat_in.entry, mat_in.entry + (mat_in.nrows * mat_in.mcols), p);
delete[] this -> entry;
should be this
for(int i=1;i<mat_in.nrows;i++)
p[i] = p[i-1] + mat_in.mcols;
std::copy(mat_in.entry[0], mat_in.entry[0] + (mat_in.nrows * mat_in.mcols), p[0]);
delete[] this -> entry[0];
delete[] this -> entry;
There's a lot of code duplication here, which you should clean up. You should also look into the copy and swap idiom which is a common way of implementing a copy assignment operator.

operator = overload in template class

Im working on matrix template class, and now i should write the "=" operator overload.
What Im trying to do is to delete the matrix that appears in the left side of the '=', and return new one that equals to the matrix that appears in the right side of the '='.
because i can't delete "this" with a distructor, I delete it "manually" in the function. but now i should make a new matrix, therefor i make a new one ("temp") and return it.
The prblem is that "temp" is really return, but it doesn't set in the matrix that appears in the left side of the '='.
The code:
Matrix<int> m (3, 4);
Matrix<int> m2(2, 5);
m2 = m;
This was the main part.
The function:
template<class T>
Matrix<T> & Matrix<T>::operator=(Matrix<T>& mat)
{
if (this==&mat)
{
return *this;
}
for (int i = 0; i < this->rows; i++)
{
delete[] this->mat[i];
}
delete[] this->mat;
Matrix<T> * temp = new Matrix<T>(mat.rows, mat.cols);
for (int i = 0; i < temp->rows; i++)
for (int j = 0; j < temp->cols; j++)
{
temp->mat[i][j] = mat.mat[i][j];
}
return *temp;
}
template<class T>
Matrix<T>::Matrix(int row, int col)
{
rows = row;
cols = col;
mat = new T*[rows];
for (int i = 0; i < rows; i++)
{
mat[i] = new T[cols];
}
rester(*this);
}
Thx!!
Use std::vector as storage (instead of manal new and delete), and just accept the copy assignment operator generated by the compiler. It's that easy.
If you absolutely want to implement the copy assignment yourself, for learning, then just express copy assignment in terms of copy construction.
To do that, first define a noexcept swap operation:
// In class definition:
friend
void swap( Matrix& a, Matrix& b )
noexcept
{
using std::swap;
// swap all data members here
}
Then the copy assignment operator can be expressed as simply
// In class definition
auto operator=( Matrix other )
-> Matrix&
{
swap( *this, other );
return *this;
}
It's popular, an idiom, because it's very simple yet exception safe.
Instead of returning a reference, which adds verbosity and some possible marginal inefficiency for no gain, you might want to just use void as return type. However, probably for historical reasons, the containers in the standard library require the copy assignment operator to return a reference to self.
You need to allocate memory for this instead of creating a temp.
template<class T>
Matrix<T> & Matrix<T>::operator=(Matrix<T>& rhs)
{
if (this==&rhs)
{
return *this;
}
// Delete current memory
for (int i = 0; i < this->rows; i++)
{
delete[] this->mat[i];
}
delete[] this->mat;
this->rows = rhs.rows;
this->cols = rhs.cols;
// Allocate new memory
// Assign values to newly allocated memory.
this->mat = new int*[rhs.rows];
for (int = 0; i < rhs.rows; ++i )
{
this->mat[i] = new int[rhs.cols];
for (int j = 0; j < rhs.cols; j++)
{
this->mat[i][j] = rhs.mat[i][j];
}
}
// Return *this.
return *this;
}
I would recommend using the suggestion given in the answer by #Cheersandhth.
Also use a different name of the argument. Don't confuse with the member variable mat and the argument mat.

C++ Memory allocation. Matrix

I looked into two different method to allocate memory for the elements of a matrix
Method n.1
int** matrix = new int*[rows];
for (int i = 0; i < rows; ++i)
matrix[i] = new int[cols];
Method n.2
int** matrix = new int*[rows];
if (rows)
{
matrix[0] = new int[rows * cols];
for (int i = 1; i < rows; ++i)
matrix[i] = matrix[0] + i * cols;
}
I can figure out what Method n.1 does, but I can't figure out what exactly is supposed to do the if clause in Method n.2 (I would implement it without and it doesn't work, with the if clause, it does...)
EDIT: Here is a code showing my problem. Why does it take so long to load (~30seconds)?
http://codepad.org/uKvI8Tk3
Codepad refuses to show the output (timeout) so if you want to run it, just compile it on your own.
Also, why cout << statements are not executed once the program starts?
Method n.3: write your own Matrix class, internally using a single std::vector<int> and being clever about access by (row,col) indices.
struct Matrix
{
explicit Matrix(unsigned int rows, unsigned int cols) : data_(rows*cols), cols_(cols) {}
const int& operator()(unsigned int row, unsigned int col) const
{
return data_[row*cols_ + col];
}
private:
std::vector<int> data_;
unsigned int cols_;
};
Edit: iff the memory overhead of a vector is an issue in the last example, you can consider using a single dynamically allocated array of length rows*cols, and make sure to call delete [] on it in the destructor.
Method n.2 is allocating a unique block to contain the sequence of all rows. Hence the first row is a pointer to the whole block. If rows==0 you have not space to hold the pointer to the (empty) space, so you cannot make the allocation.
I would steer toward method 4 suggested in the other answer:
class Matrix {
Matrix(int rows, int cols): rows_(rows), cols_(cols) {
data_ = new int[rows*cols];
}
~Matrix() {
delete[] data_;
}
int &operator()(int i,int j) {return data_[cols_*i+j];}
int operator()(int i,int j) const {return data_[cols_*i+j];}
private:
int rows_,cols_;
int *data_;
};

Bad Access Error in 2D-Array (Matricies)

I have a little bit of a problem... I understand what a EXC_BAD_ACCESS error is and I generally know how to fix it but this one has got me completely stuffed. I have this all within a class, here is one method:
double Matrix::get_element(int r, int c) const {
//Retrieve the element at row r and column c
//Should not modify the value stored in Matrix but return a double copy of the value
double currentValue = matrix[r][c];
return currentValue;
}
Now, I have another piece of my code that calls this method:
std::string Matrix::to_string() const {
std::string result;
double current;
Matrix working = *this;
std::ostringstream oss;
oss << "[";
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
current = 0.0;
current = working.get_element(i, j);
oss << " " << current << " ";
}
oss << "; ";
}
oss << "]";
result = oss.str();
return result;
}
I know that the working object has 3 rows and 3 cols at the point where working.get_element(i, j); is called. The variable list shows me just before the get_element() method, that both rows and cols are set to 3. In the method, I'm able to get the value at get_element(0, 0) but not get_element(0, 1).
I can't see why this is the case... Anyone know why or require more of my code to understand why these methods are being called?
EDIT:
Here is the header file:
class Matrix {
private:
//Any variables required
int rows;
int cols;
double **matrix;
public:
Matrix(); //Working M
~Matrix(); //Working M
Matrix(int r, int c); //Working M
int getRows();
int getCols();
void set_element(int r, int c, double val); //Working M
double get_element(int r, int c) const; //Working M
void clear(); //Working M
bool is_empty(); //Working M
bool is_identity(); //Working M
const Matrix transpose(); //Working M
int minorMat(double **dest, const int row, const int col, int order); //Working M
double get_determinent(); //Working M
double higherDeterminents(int order); //Working M
const Matrix operator+(const Matrix &rhs); //Working M
const Matrix operator-(const Matrix &rhs); //Working M
const Matrix operator*(const Matrix &rhs);
bool operator==(const Matrix &rhs); //NOT assessed
const Matrix operator*(const double &rhs);
const Matrix operator/(const double &rhs);
Matrix & operator=(const Matrix &rhs);
std::string to_string() const;
};
Do ignore the comments sorry. And this is the constructors/destructors:
Matrix::Matrix() {
//Basic Constructor
rows = 1;
cols = 1;
matrix = new double*[rows];
for (int i = 0; i < rows; ++i) {
matrix[i] = new double[cols];
}
}
Matrix::~Matrix() {
//Basic Deconstructor
for (int i = 0; i < rows; ++i) {
delete[] matrix[i];
}
delete[] matrix;
rows = NULL;
cols = NULL;
matrix = NULL;
}
Matrix::Matrix(int r, int c) {
//Empty matrix (all 0's) with r rows and c columns, if they are -ve, set to 1
rows = r;
cols = c;
if (cols < 0)
cols = 1;
if (rows < 0)
rows = 1;
matrix = NULL;
matrix = new double*[rows];
for (int i = 0; i < rows; i++) {
matrix[i] = new double[cols];
}
}
EDIT2:
Matrix & Matrix::operator=(const Matrix &rhs) {
//rhs is matrix to be copied
//rhs compied into Matrix called on
double toCopy;
for (int i = 0; i < rhs.rows; i++) {
for (int j = 0; j < rhs.cols; j++) {
toCopy = rhs.get_element(i, j);
this->set_element(i, j, toCopy);
}
}
return *this;
}
It is impossible for us to say when you do not state how you declare and initialize the matrix element. Using something like that in your CTOR should be fine:
class Matrix {
float matrix[3][3];
...
}
Don't forget to initialize it in your CTOR to something that makes sense.
Btw: why do you do this: Matrix working = *this; ?? You could simply this->get_element(i, j); instead, which would not invoke copying of your whole object. [1]
EDIT: Update since you updated your answer. You should be careful with your copy CTORs and operator=() statements. It is easily possible to make double deletes or something ugly like that.
EDIT2: I think the problem is this line:
Matrix working = *this;
You are creating a new copy working of your this object. But working gets initialized with only 1 column and 1 row (as defined in your standard CTOR). I'm not sure if you are checking the bounds when calling set_element or get_element so I guess you are writing over the bounds of your arrays.
I think the best idea is to just remove the line Matrix working = *this; and to adhere to my tip in above:
this->get_element(i, j); in std::string Matrix::to_string() const.
Your Matrix(int r, int c) allocates memory for matrix, but leaves the values it points to uninitialized. Add something like this to the constructor:
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
this->set_element(i, j, 0);
}
}
Doing like this:
int main()
{
Matrix m(3,3);
std::cout << m.to_string();
}
Output:
[ 0 0 0; 0 0 0; 0 0 0; ].
Same thing in the default constructor:
Matrix::Matrix() {
//Basic Constructor
rows = 1;
cols = 1;
matrix = new double*[rows];
for (int i = 0; i < rows; ++i) {
matrix[i] = new double[cols];
}
}
You allocated memory, but wherever matrix[0][0] points to, it's uninitialized garbage value. Do something like matrix[0][0] = 0; or whatever default value you want it to have.
Hope that helps.
Your class is violating the "big three" rule. If a class has one of a destructor, assignment operator or copy constructor then it most probably you need to have all three.
In your case you have a destructor, but no assignment operator or copy constructor, and this is going to create an UB condition when you do Matrix working = *this.
By the way there are two other problems with your code
From the comment seems that you think that new double[size] will initialize the elements to 0 and this is not true.
Most of your code is technically very bad. Your matrix class would be much easier (less code) to implement correctly using std::vector instead of pointers and dynamic memory. Of course if this is just an exercise then it make sense to avoid using std::vector.
By the way if you never heard about the "big three" rule chances are that you're trying to learn C++ with experimentation instead that by reading.
With C++ this is not a smart move... logic can be used as substitute for study if 1) the topic is highly logical, 2) if you can be told when you get it wrong.
Instead C++ is very very complex and in a few place is also quite illogical (for historical reasons) so there are parts in which logic will simply misguide you.
Moreover when you make a mistake in C++ you don't get in general an error message, but "Undefined Behavior". This basically makes very very hard to learn C++ with experimentation because even wrong code may apparently work. It is also very easy to write code that looks good and that is instead quite wrong for subtle reasons.
Instead of just experimenting you should grab a good book and read it cover to cover...