Matrix pointer deallocation issue - c++

I get this error while running the following program (it execute the code perfectly but looks like there are some issues about pointers/memory). thanks in advance for your help...
This is the message i get:
REVIEW(8310) malloc: * error for object 0x100103b80: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
(lldb)
My code:
In file Matrix.h
template <typename T>
class Matrix
{
private:
T** M;
// unsigned numCol, numRow;
unsigned minRowIndex, maxRowIndex;
unsigned minColIndex, maxColIndex;
public:
Matrix(); // default constructor
Matrix(const unsigned& _numRow,
const unsigned& _numCol,
const T& value,
const unsigned& _minRowIndex = 0,
const unsigned& _minColIndex = 0);
~Matrix();
void Print();
T& operator() (const unsigned& row, const unsigned& col);
};
template<typename T>
Matrix<T> :: Matrix()
{
maxRowIndex = 9;
maxColIndex = 9;
unsigned i,j;
M = new T*[maxRowIndex + 1];
for (i = minRowIndex; i < maxRowIndex; i++)
M[i] = new T[maxColIndex + 1];
for (i = minRowIndex; i < maxRowIndex; i++)
for (j = minColIndex; j < maxColIndex; j++)
M[i][j] = 0;
}
template<typename T>
Matrix<T> :: Matrix( const unsigned& _numRow,
const unsigned& _numCol,
const T& value,
const unsigned& _minRowIndex,
const unsigned& _minColIndex)
{
minRowIndex = _minRowIndex;
minColIndex = _minColIndex;
maxRowIndex = _minRowIndex + _numRow - 1;
maxColIndex = _minColIndex + _numRow - 1;
unsigned i,j;
M = new T*[maxRowIndex + 1];
for (i = minRowIndex; i <= maxRowIndex; i++)
M[i] = new T[maxColIndex + 1];
for (i = minRowIndex; i <= maxRowIndex; i++)
for (j = minColIndex; j <= maxColIndex; j++)
M[i][j] = value;
}
template<typename T>
Matrix<T> :: ~Matrix()
{
for (unsigned i = 0; i <= maxRowIndex; i++)
delete[] M[i];
delete[] M;
}
template<typename T>
void Matrix<T> :: Print()
{
unsigned i,j;
for (i = minRowIndex ; i <= maxRowIndex; i++)
for (j = minColIndex; j <= maxColIndex; j++)
{
cout << M[i][j] << " ";
if (j == maxColIndex)
cout << endl;
}
cout << endl;cout << endl;
}
template<typename T>
T& Matrix<T> :: operator() (const unsigned& row, const unsigned& col)
{
return M[row][col];
}
In file main.cpp
#include "Matrix.h"
using namespace std;
int s(Matrix<int> L)
{
return L(2,2);
}
int main()
{
Matrix<int> L (5,5,100);
cout << "L(2,2) = " << s(L) << endl << endl;
return 0;
}

Classes that allocate fields using new and delete should have copy constructors and overload operator=. Failing to do so will use the default forms where fields are simply copied.
In your case, T** M is copied during the call to s(L) and upon return, the copy is destructed, causing deletes for all the arrays. At the end of main, another destruction takes place, but now the pointers refer to already freed blocks.
For function s, you might also pass a reference to avoid copying (but this doesn't solve the general problem).

Related

how to put all the numbers in the white boxes on the chessboardArray, in C++?

I wrote the following code for creating a chessboard using 2D Arrays in C++ :
#include <iostream>
#include <iomanip>
#include <array>
using namespace std;
Here is the ChessBoardArray class:
class ChessBoardArray
{
protected:
class Row
{
public:
Row(ChessBoardArray &a, int i): cba(a), row(i){}
int & operator[] (int i) const
{
return cba.select(row, i);
}
private:
ChessBoardArray &cba;
int row;
};
class ConstRow
{
public:
ConstRow(const ChessBoardArray &a, int i): cba(a), row(i){}
int operator[] (int i) const
{
return cba.select(row, i);
}
private:
const ChessBoardArray &cba;
int row;
};
unsigned int my_size;
int my_base;
int *data;
The loc function is for finding the location of an element. It corresponds the elements of the 2D array to the corresponding position.
unsigned int loc(int i, int j) const throw(out_of_range)
{
int di = i - my_base, dj = j - my_base;
if(di < 0 || di >= my_size || dj < 0 || dj >= my_size) throw out_of_range("invalid index");
return di * my_size + dj;
}
public:
ChessBoardArray(unsigned size = 0, unsigned base = 0)
{
my_size = size;
my_base = base;
data = new int[my_size * my_size];
}
ChessBoardArray(const ChessBoardArray &a)
{
my_size = a.my_size;
my_base = a.my_base;
data = new int[my_size * my_size];
for(int i = 0; i < my_size*my_size; i++) data[i] = a.data[i];
}
~ChessBoardArray()
{
delete [] data;
}
ChessBoardArray & operator= (const ChessBoardArray &a)
{
this -> ~ChessBoardArray();
my_size = a.my_size;
my_base = a.my_base;
data = new int[my_size * my_size];
for(int i = 0; i < my_size*my_size; i++) data[i] = a.data[i];
return *this;
}
int & select(int i, int j)
{
return data[loc(i, j)];
}
int select(int i, int j) const
{
return data[loc(i, j)];
}
const Row operator[] (int i)
{
return Row(*this, i);
}
const ConstRow operator[] (int i) const
{
return ConstRow(*this, i);
}
friend ostream& operator<< (ostream &out, const ChessBoardArray &a)
{
for(int i = a.my_base; i <= a.my_size; i++)
{
for(int j = a.my_base; j <= a.my_size; j++)
{
out << setw(4) << a.data[a.loc(i, j)];
}
out << endl;
}
return out;
}
};
The condition for a number to be in a white box is i%2 == j%2. Where should i add the condition in my code?
I tried putting it inside the loc function but it got me some errors.

C++ Matrix Operator+

The method template <class T> const Matrix<T> Matrix<T>::operator+(const Matrix<T> &rhs) const for program matrix.cc should be able to return the sum of calling object's matrix and rhs's matrix as a new object. Also, the lhs and rhs rows and cols will be equal.
The error output that I am receiving from the compiler is:
[hw7] make clean && make bin/test_add && ./bin/test_add UserSettings ✱
rm -f bin/*
g++ -std=c++11 -Wall -I inc -I src -c src/test_matrix_add.cc -o bin/test_matrix_add.o
g++ -std=c++11 -Wall -I inc -I src -o bin/test_add bin/test_matrix_add.o
Testing Matrix::operator+
Expected Matrix2[0][0]: 3.0, Actual: 1
FAILED
Could someone let me know why I receive this "Failed" output when I know I pass the // TEST MUL ASSIGMENT OP CORRECT RETURN section.
Here is my matrix.cc:
#include <matrix.h>
template <class T>
Matrix<T>::Matrix() {
rows_ = 0;
cols_ = 0;
m_ = nullptr;
}
template <class T>
Matrix<T>::Matrix(unsigned int rows, unsigned int cols)
: rows_(rows), cols_(cols) {
m_ = new T *[rows_];
for (unsigned int i = 0; i < rows_; ++i) {
m_[i] = new T[cols_];
}
}
template <class T>
Matrix<T>::Matrix(const Matrix<T> &that) {
rows_ = that.rows_;
cols_ = that.cols_;
m_ = new T *[rows_];
for (unsigned int i = 0; i < rows_; ++i) {
m_[i] = new T[cols_];
for (unsigned int j = 0; j < cols_; ++j) {
m_[i][j] = that.m_[i][j];
}
}
}
template <class T>
Matrix<T>::~Matrix() {
for (unsigned int i = 0; i < rows_; ++i) {
delete[] m_[i]; // delete columns
}
delete[] m_; // delete columns
}
template <class T>
T Matrix<T>::Get(unsigned int row, unsigned int col) const {
if (row > rows_ && col > cols_) {
throw std::out_of_range("error: index out of range");
}
return this->m_[row][col];
}
template <class T>
const Matrix<T> &Matrix<T>::operator=(const Matrix<T> &rhs) {
if (this == &rhs) {
return *this;
} // returns the address
for (unsigned int i = 0; i < rows_; ++i) {
delete[] m_[i];
}
delete[] m_;
rows_ = rhs.rows_;
cols_ = rhs.cols_;
m_ = new T *[rows_];
for (unsigned int i = 0; i < rows_; ++i) {
m_[i] = new T[cols_];
for (unsigned int j = 0; j < cols_; ++j) {
m_[i][j] = rhs.m_[i][j];
}
}
return *this;
}
template <class T>
const Matrix<T> &Matrix<T>::operator*=(T rhs) {
for (unsigned int i = 0; i < rows_; ++i) {
for (unsigned int j = 0; j < cols_; ++j) {
m_[i][j] *= rhs;
}
}
return *this;
}
template <class T>
const Matrix<T> Matrix<T>::operator+(const Matrix<T> &rhs) const {
if (!(this->cols_ == rhs.cols_) || (this->rows_ == rhs.rows_)) {
std::cout << "Cannont add matrices. Wrong dimensions\n";
exit(0);
}
Matrix<T> lhs;
lhs.rows_ = this->rows_;
lhs.cols_ = this->cols_;
for (unsigned int i = 0; i < lhs.rows_; ++i) {
for (unsigned int j = 0; j < lhs.cols_; ++j) {
lhs[i][j] += rhs[i][j];
}
}
return lhs;
}
Here is my matrix.h:
#include <cassert>
// using assert
#include <exception>
#include <iostream>
template <class T>
class Matrix {
public:
friend class MatrixTester;
Matrix(); // for testing, useless in practice
Matrix(unsigned int rows, unsigned int cols);
Matrix(const Matrix<T> &that);
~Matrix();
T Get(unsigned int row, unsigned int col) const;
const Matrix<T> &operator=(const Matrix<T> &rhs);
const Matrix<T> &operator*=(T rhs);
const Matrix<T> operator+(const Matrix<T> &rhs) const;
private:
T **m_;
unsigned int rows_;
unsigned int cols_;
};
#include <matrix.cc> //NOLINT
This is my test_matrix_add.cc tester:
#include <test_matrix.h>
int main(int argc, char** argv) {
MatrixTester tester;
cout << "Testing Matrix::operator+" << endl;
if (tester.Test_AddOp()) {
cout << " PASSED" << endl;
return 0;
}
cout << " FAILED" << endl;
return 1;
}
bool MatrixTester::Test_AddOp() const {
const int kRows = 4, kCols = 5;
Matrix<double> m1;
m1.m_ = new double*[kRows];
for (unsigned int i = 0; i < kRows; ++i) {
m1.m_[i] = new double[kCols];
for (unsigned int j = 0; j < kCols; ++j)
m1.m_[i][j] = (i + 1.0) * (j + 1.0);
}
m1.rows_ = kRows;
m1.cols_ = kCols;
// TEST ADDITION CORRECTNESS
Matrix<double> m2;
m2 = m1;
// + m1 + m1;
if (m2.m_[0][0] != 3) {
cout << " Expected Matrix2[0][0]: 3.0, Actual: " << m2.m_[0][0] << endl;
return false;
}
if (m2.m_[1][3] != 24.0) {
cout << " Expected Matrix2[1][3]: 24.0, Actual: " << m2.m_[1][3] << endl;
return false;
}
if (m2.m_[2][2] != 27.0) {
cout << " Expected Matrix2[2][2]: 27.0, Actual: " << m2.m_[2][2] << endl;
return false;
}
if (m2.m_[3][4] != 60.0) {
cout << " Expected Matrix2[2][2]: 60.0, Actual: " << m2.m_[2][2] << endl;
return false;
}
return true;
}
Firstly, there is way too much code here.
To address your problem, I see don't see you allocating memory to lhs.m_. This is a problem because you initialize lhs with the default constructor, which only assigns this->m_ to a nullptr.
To fix this, this should work (although untested):
template <class T>
const Matrix<T> Matrix<T>::operator+(const Matrix<T>& rhs) const
{
if (!(this->cols_ == rhs.cols_) || (this->rows_ == rhs.rows_))
{
std::cout << "Cannot add matrices. Wrong dimensions\n";
exit(0);
}
Matrix<T> lhs;
lhs.rows_ = this->rows_;
lhs.cols_ = this->cols_;
// Allocate memory for `lhs.m_`, like you did in your 2nd constructor
lhs.m_ = new T* [rows_];
for (unsigned i = 0; i < rows_; ++i)
{
m_[i] = new T[cols_];
}
// [End] allocation
for (unsigned int i = 0; i < lhs.rows_; ++i)
{
for (unsigned int j = 0; j < lhs.cols_; ++j)
{
lhs[i][j] += rhs[i][j];
}
}
return lhs;
}
Also, somewhat unrelated, be careful that you consistently treat m_ as a double-pointer. I didn't read all your code, but just be cautious. And also remember that you have to deallocate all the memory you allocated with new in your destructor. Personally, I believe you should use smart pointers from <memory> (e.g. std::unique_ptr, etc), which you can learn more about here. Using smart pointers would make the pointers deallocate the memory on their own and you wouldn't have to worry about memory leaks.
Edit 1
As walnut stated, a better solution would be to just call the 2nd constructor, which will allocate the memory for you. So, your revised function would be:
template <class T>
/**
Note:
> When you call this function (e.g. Matrix<T> new_mat = mat1 + mat2),
`mat1` is `this` and `mat2` is what you're calling `rhs`. I've done
some renaming and corrected your logic errors here
*/
const Matrix<T> Matrix<T>::operator+(const Matrix<T>& other) const
{
if (!(this->cols_ == other.cols_) || (this->rows_ == other.rows_))
{
std::cout << "Cannot add matrices. Wrong dimensions\n";
exit(0);
}
// Call the 2nd constructor
Matrix<T> res(this->rows_, this->cols_);
for (unsigned i = 0; i < res.rows_; ++i)
{
for (unsigned j = 0; j < res.cols_; ++j)
{
res.m_[i][j] = this->m_[i][j] + other.m_[i][j];
}
}
return res;
}
Edit 2
The above code has been correct to add the matrices correctly, as per #walnut's comment.

Overloading << operator to print the elements of a matrix in a template class

why am I having an error on the operator '[]'. I wanted to print the contents of my matrix. If i can't use the brackets, what could i do then?
here's a sample of the code:
#include <iostream>
#include <vector>
template <typename T>
class Matrix {
private:
int m; int n;
std::vector<T> x;
std::vector<std::vector<int>> Mat;
public:
Matrix (const unsigned int &m, const unsigned int &n, std::vector<T> x);
Matrix(const Matrix &M);
Matrix<T> operator = (const Matrix &M);
// Matrix<T> operator [](const int &index);
friend std::ostream& operator << (std::ostream& os, const Matrix<T> &M) {
os << "[";
for (int i = 0; i< M.m; i++){
for (int j = 0; j< M.n; j++){
os << M[i][j] << ' ';
}
os << '\n';
}
os << "]\n";
return os;
}
};
I have fixed the errors. But it doesn't print my matrix.
This is my main:
int main(){
std::vector<int> x = {1,2,3,4};
Matrix<int> A{2,2,x};
Matrix<int> B{2,2,x};
std::cout << A;
std::cout << B;
return 0;
}
And this is my constructor, I needed to make a matrix from a vector where I specify the rows and columns.
template <typename T>
Matrix<T>::Matrix (const unsigned int &m, const unsigned int &n, std::vector<T> x){ //constructor
this -> m = m;
this -> n = n;
this -> x = x;
int index = 0;
for (int i = 0; i<m; i++){
for (int j = 0; j<n; j++){
Mat[i][j] = x[index];
index++;
}
}
}
The issue is this line:
os << M[i][j] << ' ';
Because M is of type Matrix<T> and you haven't defined [] operator, any attempts to use [] operator will give you error.
Instead, You should use data member Mat.
friend std::ostream& operator << (std::ostream& os, const Matrix<T> &M) {
os << "[";
for (int i = 0; i< M.m; i++){
for (int j = 0; j< M.n; j++){
os << M.Mat[i][j] << ' '; // using M.Mat instead of M
}
os << '\n';
}
os << "]\n";
return os;
}
Edit:
As per your updated code, you may get a nice SIGSEGV error (Segmentation Fault) issue. Why? Simple. You are not resizing your data member Mat.
You have to do this:
template <typename T>
Matrix<T>::Matrix (const unsigned int &m, const unsigned int &n, std::vector<T> x){ //constructor
this -> m = m;
this -> n = n;
this -> x = x;
int index = 0;
// resizing Matrix according to our need i.e. m rows and n columns
Mat.resize(m);
for (unsigned int i = 0; i < Mat.size(); i++) {
Mat[i].resize(n);
}
for (unsigned int i = 0; i<m; i++){
for (unsigned int j = 0; j<n; j++){
Mat[i][j] = x[index];
index++;
}
}
}
You have different mistakes in your code:
1.- Your constructor:
Matrix<T>::Matrix (const unsigned int &m, const unsigned int &n, std::vector<T> x)
it's not a good idea to pass a vector by value, its always better to pass it by reference, and never pass an integer by const reference, pass it by value:
Matrix<T>::Matrix (unsigned int m, unsigned int n, const std::vector<T>& x)
2.- This is not an error, but you don't usually need to use "this->", and its better to construct an object like:
Matrix<T>::Matrix (unsigned int m0, unsigned int n0, const std::vector<T>& x0)
: m{m0}, n{n0}, x{x0} {...}
3.- I don't understand why you make 2 copys of the same elements: one in your vector x, and other with M. Your wasting your memory. Maybe with x is enough?
4.- You define m and n as signed int, but in your constructor you use "unsigned" int. Which one do you want to use?
I propose this changes:
1.- If you want to access to an element (i,j), write the operator:
Matrix& operator()(unsigned int i, unsigned int j);
its easy using your vector x.
2.- To write all the elements you can write something like:
std::ostream& operator << (std::ostream& os, const Matrix<T>& M) {
os << "[";
for (int i = 0; i< M.rows(); ++i){
for (int j = 0; j< M.cols(); ++j){
os << M(i, j) << ' ';
}
os << '\n';
}
os << "]\n";
return os;
}
and this is not a friend function (if you define rows() and cols()).
your operator[] returns a Matrix. You should change it to your template value.

Weird segmentation fault 11

There are two files:
Matrix.hpp:
template <typename T>
class Matrix {
private:
size_t rows = 0;
size_t cols = 0;
T* data = nullptr;
public:
Matrix() = default;
~Matrix();
Matrix(size_t n, size_t m);
T& operator() (size_t i, size_t j);
};
template <typename T>
Matrix<T>::Matrix(size_t n, size_t m) : rows(n), cols(m) {
try {
data = new T[rows*cols];
} catch (const std::bad_alloc& e) {
std::exit(EXIT_FAILURE);
}
};
template <typename T>
Matrix<T>::~Matrix() {
delete[] data;
}
template <typename T>
T& Matrix<T>::operator()(size_t i, size_t j) {
if (i < rows && i >= 0 && j < cols && j >= 0) {
return data[(i+1)*cols + (j+1)];
} else {
throw std::logic_error("matrix indices out of range");
}
}
and
Main.cpp:
#include <iostream>
#include "Matrix.hpp"
int main() {
size_t n, k;
std::cin >> n >> k;
Matrix<long double> m = {n, k};
for (size_t i = 0; i < m.getNumRows(); ++i) {
for (size_t j = 0; j < m.getNumCols(); ++j) {
std::cin >> m(i,j);
}
}
for (size_t i = 0; i < m.getNumRows(); ++i) {
std::cout << "\n";
for (size_t j = 0; j < m.getNumCols(); ++j) {
std::cout << m(i, j) << " ";
}
}
return 0;
}
When I'm entering something like:
1 2 3 4
I can get
3 4
as answer but sometimes the same input causes Segmentation fault 11 moreover when I'm changing template argument from long double to int, error disappears. How can I fix it?
Your operator function is accessing data outside its bounds.
Passing (0,0) to the function should return data[0]. Currently it returns data[2].
Change line
return data[(i+1)*cols+(j+1)];
to
return data[i*cols+j];

= operator for a matrix class behaving weird

CPP
#include "del2.h"
Matrix::Matrix()
{
dArray = NULL;
}
bool Matrix::isValid() const
{
if (dArray == NULL)
return false;
return true;
}
Matrix::~Matrix()
{
delete [] dArray;
}
Matrix::Matrix(unsigned int nRows)
{
rows = nRows;
columns = nRows;
dArray = new double[nRows * nRows];
for (unsigned int i = 0; i < nRows; i++)
{
for (unsigned int n = 0; n < nRows; n++)
{
at(i,n) = 0;
}
}
at(0,0) = 1;
at(rows-1,columns-1) = 1;
}
Matrix::Matrix(unsigned int nRows, unsigned int nColumns)
{
dArray = new double[nRows * nColumns];
rows = nRows;
columns = nColumns;
for (unsigned int i = 0; i < nRows; i++)
for (unsigned int n = 0; n < nColumns; n++)
dArray[i * columns + n] = 0;
}
const Matrix Matrix::operator =(const Matrix & rhs)
{
columns = rhs.getColumns();
rows = rhs.getRows();
delete [] dArray;
dArray = new double[rows * columns];
for (int row = 0; row < rows; row++)
for (int column = 0; column < columns; column++)
at(row,column) = rhs.at(row,column);
return *this;
}
std::ostream & operator <<( std::ostream & out, const Matrix & classPrint )
{
if (!classPrint.isValid())
return out;
int rows = classPrint.getRows();
int columns = classPrint.getColumns();
out << std::endl;
for (int i = 0; i < rows; i++)
{
out << "| ";
for (int n = 0; n < columns; n++)
out << classPrint.at(i,n) << " ";
out << "|" << std::endl;
}
out << endl;
return out;
}
HEADER:
#ifndef DEL2
#define DEL2
#include <iostream>
using namespace std;
class Matrix
{
private:
int rows;
int columns;
double * dArray;
public:
~Matrix();
Matrix();
explicit Matrix(unsigned int nRows);
Matrix(unsigned int nRows, unsigned int nColumns);
const Matrix operator =(const Matrix & rhs);
const double at(int row, int column) const
{ return dArray[ row*this->columns + column ]; }
double & at( int row, int column )
{ return dArray[ row*this->columns + column ]; }
const int getRows() const {return rows;}
const int getColumns() const {return columns;}
bool isValid() const;
};
std::ostream & operator <<( std::ostream & out, const Matrix & classPrint );
#endif // MATRIX
Main:
#include <iostream>
#include "del2.h"
using namespace std;
int main()
{
Matrix A;
Matrix B(10);
A = B;
cout << A;
return 0;
}
When I run this, the following happens:
The first index, matrix[0] of A, always becomes some weird number like 2.22323e-306. I don't understand why. Even when I try to set "at(0,0) = 1;" in the operator = - function after the loop, it still doesn't have 0.
The problem is here
const Matrix operator =(const Matrix & rhs);
should be
const Matrix& operator =(const Matrix & rhs);
and the definition should be
const Matrix& Matrix::operator =(const Matrix & rhs)
{
if (&rhs == this)
return *this;
Otherwwise operator= is returning a copy of the Matrix which will have dArray same as the original Matrix. Your data will be deleted when the temporary returned array goes out of scope.
Be carefull the operator = is not correct
Matrix & operator = (const Matrix & rhs){
if (&rhs != this){
// Your stuff here
}
return *this;
}
Calling delete [] on a null array is undefined. It can crash.
You must also define the copy constructor