I have been having a lot of trouble getting my overloaded operators to properly with each other, especially in cases such as a=a+b+c
When I execute the program, I get an error: "Unhandled exception at 0x01201f10 in Project1_v3.exe: 0xC0000005: Access violation reading location 0xcccccccc." But I am not sure exactly what that means or where it comes from.
I have posted all relevant code including my test file. I would really appreciate any insights you have about what could be causing this problem.

Implementation file:

#include "matrix.h"

//Constructors

matrix::matrix(int r, int c)
	//create matrix with specified row and column dimensions
{
	try
	{
		if ((r<=0)||(c<=0))
			throw invalid_argument ("Matrix row and column arguments must be greater than zero.");
	row=r;
	column=c;
	}
	catch (exception & ex)
	{
		cout<<"Error: "<<ex.what()<<endl;
	}

	try
	{
		data=new matrixData * [row];
		for (int i=0; i<row; i++)
			data[i]=new int [column];
	}
	catch (exception & ex)
	{
		cout<<"Error: "<<ex.what()<<endl;
	}
	fillMatrix();
}
//Destructor
matrix::~matrix ()
{
	for (int i=0; i<row; i++)
		delete [] data[i];
	delete [] data;
}
matrix & matrix::operator=( const matrix & in)
{
	if ((row!=in.getRows())||(column!=in.getColumns()));
	{
		column=in.getColumns();
		row=in.getRows();
	}
	if (!(*this==in))
	{
		for (int i=0; i<row; i++)
		{
			for (int j=0; j<column; j++)
				data[i][j]=in.getEntry(i, j);
		}
	}
	return *this;
}

matrix & matrix::operator+=(const matrix & in)
{
	try
	{
		if ((column!=in.getColumns())||(row!=in.getRows()))
			throw invalid_argument ("Matricies must be of equal size.");
	}
	catch (exception & ex)
	{
		cout<<"Error: "<<ex.what()<<endl;
		return *this;
	}
	for (int i=0; i<row; i++)
	{
		for (int j=0; j<column; j++)
			this->setEntry(i,j,((data[i][j])+in.getEntry(i,j)));
	}
	return *this;
}  
matrix & matrix::operator+(const matrix & in)
	//Computes and returns the sum of two matricies
{
	return matrix (*this) += in;
}
ostream& operator<<(ostream& output, const matrix & in)
	//print matrix to standard output
{
	for (int i=0; i<in.getRows(); i++)
	{
		output<<endl;
		for (int j=0; j<in.getColumns(); j++)
		{
			output.width(3);
			output<<in.getEntry(i,j)<<"   ";
		}
	}
	output<<endl;
	return output;
}

//Helper Functions used to implement matrix class member functions

void matrix::fillMatrix()
{
	for (int i=0; i<row; i++)
	{
		for (int j=0; j<column; j++)
			data[i][j]=(matrixData) i-j;
	}
}

int matrix::getColumns()const
{
	return column;
}

int matrix::getRows() const
{
	return row;
}

int matrix::getEntry(const int r_index, const int c_index) const
{
	return data[r_index][c_index];
}

void matrix::setEntry (const int r_index, const int c_index, const matrixData value)
{
	data[r_index][c_index]=value;
}

Test File:

int main()
{
   matrix a(3, 4);
   matrix b(3, 4); 
   matrix c(4, 4); 
   matrix d(4, 4);
   matrix e(4, 4);
   matrix f(4, 4);
   matrix h(4, 4);
   
   if ( a != b ) 
   {
   	 cout << "Matrix a and b are not equal" << endl;
     cout << "a = " << a << endl;
     cout << "b = " << b << endl;
   };
    	
  e += f;

   cout << "f = " << f << endl;
   cout << "e -= f = " << e << endl;
   f = e = d; 
   h = d + e + f; //error.
   cout << "d = " << d << endl;
   cout << "e = " << e << endl;
   cout << "f = " << f << endl;
   cout << "h = " << h << endl;

   if ( h == e ) cout << "Matrix h and e are the same" << endl;
   else 
   {
   	 cout << "Matrix h and e are not equal" << endl;
     cout << "h = " << h << endl;
     cout << "e = " << e << endl;
   }
   
   return 0;
}

Recommended Answers

All 13 Replies

Can you post your header up? I can recreate most of it but it's time consuming to do so. More than likely you have an exception that is sneaking past your catch statements but I am not certain of that.

Header file

#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <stdexcept>

using namespace std;

typedef int matrixData;
class matrix
{
// overloaded operator<< for printing matrix to standard output
	friend ostream& operator<<(ostream&, const matrix &); 
public:
// Constructors
matrix(int row_input, int column_input); //creates new matrix with specified dimensions
//matrix (const matrix &); //Copy constructor
// Destructor: must deallocate memory allocated in constructor
~matrix();
// overloaded matrix operators
bool operator==(const matrix &);
bool operator!=(const matrix &);
matrix & operator=(const matrix &);
matrix & operator+=(const matrix &);
matrix & operator+(const matrix &);

private:
int row; // the row size of the matrix
int column; // the column size of the matrix
matrixData **data; // dynamically allocated array storage
void fillMatrix(); //initializes data contained in a matrix
int getColumns() const;
int getRows() const;
int getEntry (const int, const int) const;
void setEntry (const int, const int, const matrixData);
}; // end class

Why do you have "matrix" on line 79 of your implementation file? Were you trying to cast *this? There's no need to do so. I'm getting responses without crashing, but check they are the right ones.

A few quick notices,

1) These two are declared and used, but not implemented
bool operator==(const matrix &);
bool operator!=(const matrix &);
The code should not actually compile because of that, isn't your compiler saying anything?

2) There is no copy constructor i.e. matrix(const matrix &) , you absolutely need one, because of ( matrix (*this) ) . Now you are using the compiler-generated copy constructor, which causes you to delete memory twice in the destructor.

3) avoiding self-assignment
Now you have

if (!(*this==in))

however, that checks for equality, not self-assignment. One way to do that is

if (this == &in)
    return *this;

For some more advice, see C++ FAQ

4) There is an extra semicolon; if ((row!=in.getRows())||(column!=in.getColumns())); Once you get those things in order, you might post back with the revised code.

In general, yet a couple of major things to think of:
- managing throw/catch()
- resizing of a matrix wrt. memory corruption/leaks

you absolutely need one, because of ( matrix (*this) )

Parsing error in my brain in regards to my last post there. I got it now. Apologies.

I had implemented == and != (I had thought they were inline in the header) so I hadn't run into that but it's true that as it were they were non-existent.

Another observation: I'm thinking that += should use + operator, not the other way around.

Thank you very much for your help. I have made some changes to my code and it is re-posted below. A couple of observations from testing further:
1. c= a+b exhibits strange behavior that I can't seem to figure out. The addition portion of the operation executes normally, but when it gets to the = operation, the output screen displays a lot of blank lines, and I get a message from visual studio that "Project1_v3.exe: Native' has exited with code -1073741510 (0xc000013a)"
2. a+=b
a=c; executes as it should and produces a correct result
3. When execution gets to the end of the test program, I get "Unhandled exception at 0x66aa31ea (msvcr90d.dll) in Project1_v3.exe: 0xC0000005: Access violation reading location 0xccccccc0." This makes me think there may be something wrong with my destructor

Header:

#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <stdexcept>

using namespace std;

typedef int matrixData;
class matrix
{
// overloaded operator<< for printing matrix to standard output
	friend ostream& operator<<(ostream&, const matrix &); 
public:
// Constructors
matrix(int row_input, int column_input); //creates new matrix with specified dimensions
matrix (const matrix &); //Copy constructor
// Destructor: must deallocate memory allocated in constructor
~matrix();
// overloaded matrix operators
bool operator==(const matrix &);
bool operator!=(const matrix &);
matrix & operator=(const matrix &);
matrix & operator+=(const matrix &);
matrix & operator-=(const matrix &);
matrix & operator*=(const matrix &);
matrix & operator+(const matrix &);
matrix & operator-(const matrix &);
matrix & operator*(const matrix &);

private:
int row; // the row size of the matrix
int column; // the column size of the matrix
matrixData **data; // dynamically allocated array storage
void fillMatrix(); //initializes data contained in a matrix
int getColumns() const;
int getRows() const;
int getEntry (const int, const int) const;
void setEntry (const int, const int, const matrixData);
}; // end class

Implementation

#include "matrix.h"

//Constructors

matrix::matrix(int r, int c)
	//create matrix with specified row and column dimensions
{
	try
	{
		if ((r<=0)||(c<=0))
			throw invalid_argument ("Matrix row and column arguments must be greater than zero.");
	row=r;
	column=c;
	}
	catch (exception & ex)
	{
		cout<<"Error: "<<ex.what()<<endl;
		return;
	}

	try
	{
		data=new matrixData * [row];
		for (int i=0; i<row; i++)
			data[i]=new int [column];
	}
	catch (exception & ex)
	{
		cout<<"Error: "<<ex.what()<<endl;
		return;
	}
	fillMatrix();
}

 matrix::matrix (const matrix & in)
	//copy constructor: creates a new matrix that is identical to matrix in
{
	row=in.getRows();
	column=in.getColumns();
		try
	{
		data=new matrixData * [row];
		for (int i=0; i<row; i++)
			data[i]=new int [column];
	}
	catch (exception & ex)
	{
		cout<<"Error: "<<ex.what()<<endl;
	}
	for (int i=0; i<row; i++)
	{
		for (int j=0; j<column; j++)
			data[i][j]=in.getEntry(i,j);
	}
}

matrix::~matrix ()
{
	for (int i=0; i<row; i++)
		delete [] data[i];
	delete [] data;
}
bool matrix::operator==(const matrix & in)
{
	bool result=true;
	if ((row!=in.getRows())||(column!=in.getColumns()))
		result=false;
	for (int i=0; i<row; i++)
	{
		for (int j=0; j<column; j++)
		{
			if (in.getEntry(i,j)!=data[i][j])
				result=false;
		}
	}
	return result;
}

bool matrix::operator!=(const matrix & in)
{
	return !(*this==in);
}

matrix & matrix::operator=( const matrix & in)
{
	if ((row!=in.getRows())||(column!=in.getColumns()))
	{
		column=in.getColumns();
		row=in.getRows();
	}
	if (!(this==&in))
	{
		for (int i=0; i<row; i++)
		{
			for (int j=0; j<column; j++)
				data[i][j]=in.getEntry(i, j);
		}
	}
	return *this;
}

matrix & matrix::operator+=(const matrix & in)
{
	try
	{
		if ((column!=in.getColumns())||(row!=in.getRows()))
			throw invalid_argument ("Matricies must be of equal size.");
	}
	catch (exception & ex)
	{
		cout<<"Error: "<<ex.what()<<endl;
		return *this;
	}
	for (int i=0; i<row; i++)
	{
		for (int j=0; j<column; j++)
		     data[i][j]=(data[i][j]+in.getEntry(i,j));
	}
	return *this;
}  

matrix & matrix::operator+(const matrix & in)
	//Computes and returns the sum of two matricies
{
	return matrix (*this) += in;
}

ostream& operator<<(ostream& output, const matrix & in)
	//print matrix to standard output
{
	for (int i=0; i<in.getRows(); i++)
	{
		output<<endl;
		for (int j=0; j<in.getColumns(); j++)
		{
			output.width(3);
			output<<in.getEntry(i,j)<<"   ";
		}
	}
	output<<endl;
	return output;
}

//Helper Functions used to implement matrix class member functions

void matrix::fillMatrix()
{
	for (int i=0; i<row; i++)
	{
		for (int j=0; j<column; j++)
			data[i][j]=(matrixData) i-j;
	}
}

int matrix::getColumns()const
{
	return column;
}

int matrix::getRows() const
{
	return row;
}

int matrix::getEntry(const int r_index, const int c_index) const
{
	return data[r_index][c_index];
}

void matrix::setEntry (const int r_index, const int c_index, const matrixData value)
{
	data[r_index][c_index]=value;
}

Test

#include "matrix.h"
#include <iostream>
#include <iomanip>
#include <stdlib.h>

using namespace std;

int main()
{
   matrix a(3, 4);
   matrix b(3, 4); 
   matrix c(3, 4); 
   matrix d(4, 3);
   matrix e(3, 3);

a+=b;
c=a;
c=a+b;
 

   cout << "a = " << a << endl;
   cout << "b = " << b << endl;
   cout << "c = a + b  = " << c << endl;

  matrix f(5, 5); 

      cout << "trying to add two different matrix sizes: " << endl;
      cout << "c = a + f " << endl;

      c = a + f; 

   cout << endl << "trying to allocate a matrix of size <= 0: " << endl;
   cout << "matrix h(5, 0); " << endl;

   matrix h(5, 0); 

   {
      matrix h(3, 6); 
      cout << endl << "Reallocated matrix h to be the right size: " << endl;
      cout << "d = " << d << endl;
      cout << "h = " << h << endl;
   }


   return 0;
}

I didn't immediately find the solution to the problem but part of the problem is in the += operator, it keeps saying your matrices are different sizes and returning *this.

if ((column!=in.getColumns())||(row!=in.getRows()))
{
	cout <<this->getRows()<<" "<<this->getColumns()<<endl;
	cout <<in.getRows()<<" "<<in.getColumns()<<endl;
	throw invalid_argument ("Matricies must be of equal size.");
}

I get 3 4 for a which is presumably correct but 5 5 for b which is not.

Just wanted to give you a lead.

Disregard the above, I didn't see that you were trying to do that on purpose further down in main().

In the + operator code, change

return matrix (*this) += in;

-to-

*this += in;
return *this;

It seems to work...

Thank you so much for your help. It looks like I have got the + operator working properly now!
The only remaining problem that I continue encountering is with the destructor. Every time I run the program, I get an error at the end related to an unhandled exception. All lines of the test program seem to execute before the error actually occurs. Any ideas about what is wrong with the destructor?

It's your first h matrix that's fouling things up. You are catching the exception of the first try, but then in the second one you're allocating the memory for it anyway. You end up creating a bunch of rows of 0 columns (that perhaps fail silently?) and so when you go to delete something that never existed you get the exception. That may not be exactly the case but it's something along those lines.
Exceptions in constructors are tricky and there's a lot written about them. I'm not sure exactly what you need but probably skipping that second try block when the first fails would work.
Your second h matrix clears fine, as it has it's own scope within the braces so it evaporates after that closing brace.

Thanks for the insight. Further testing shows that it definitely is that first h matrix causing problems, so I'll have to do some research on exceptions in constructors. At least now I know what I'm looking for, thanks.

Look into the finally {} block too. I regret that I don't have much expertise in this area.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.