Dynamically allocated 2D array

May 22, 2016 at 6:15pm
Hello,

I am programming this in visual studio proff. 2015 and I seem to be running into a problem. In my program, the Matrix class used to be made of a large 2D array, I wanted the size of the matrix to be chosen so I decided to switch over to a dynamically allocated array of arrays. This worked through my entire program except when calling the overloaded * operator, in Matrix.cpp, I get the error
"Run-Time Check Failure #3 - T".

Any assistance would be greatly appreciated!

Note: This is my first time dynamically allocating an pointer array of pointer arrays.


main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include"Matrix.h"


int main()
{
	Matrix matrix1;
	Matrix matrix2;
	int row, col;
	cout << "Please enter the size of the first matrix separating the rows and columns by a space (i.e. row col)." << endl;
	cin >> row >> col;
	matrix1.setRowSize(row);
	matrix1.setColSize(col);
	matrix1.setName("Matrix 1");
	matrix1.inputValues();
	cout << "Please enter the size of the second matrix separating the rows and columns by a space (i.e. row col)." << endl;
	cin >> row >> col;
	matrix2.setRowSize(row);
	matrix2.setColSize(col);
	matrix2.setName("Matrix 2");
	matrix2.inputValues();

	string choice;
	while (choice != "!")
	{
		cout << endl;
		matrix1.print();
		matrix2.print();

		cout << "Enter your choice from the list below: " << endl;
		cout << "1. Multiplication operation" << endl;
		cout << "2. Copy operation" << endl;
		cout << "! to exit" << endl;
		cin >> choice;

		if (choice == "1")
		{
			cout << endl << "1. Multiplication operation" << endl;

			//Matrix matrix3;
			Matrix matrix3(matrix1*matrix2);
			matrix3.setName("Matrix 3");
			cout << "The result of multiplying the two matricies is: " << endl;
			matrix3.print();
		}
		else if (choice == "2")
		{
			cout << "2. Copy operation" << endl;
			matrix2 = matrix1;
		}

	}

	return 0;
}




Matrix.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#ifndef MATRIX_H
#define MATRIX_H

#include<iostream>
#include<string>
#include<iomanip>

using namespace std;

const int MAXROW = 100;
const int MAXCOL = 100;

class Matrix 
{
private:
	string name;
	int rowSize;
	int colSize;
	double **matrix;

public: 
	Matrix(); //Defult constructor
	~Matrix();
	Matrix(const Matrix& original); //copy constructor

	void setRowSize(const int i); //sets the number of rows of the matrix
	void setColSize(const int j); //sets the number of columns of the matrix
	void setName(const string name1); //sets the name of the matrix
	void inputValues(); //This function askes the user to input values of the matrix
	void print(); //prints the matrix

	Matrix& operator=(const Matrix& original);
	Matrix& operator*(const Matrix& original);

};
#endif 



Matrix.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include"Matrix.h"

Matrix::Matrix()
{
	name = "";
	rowSize = 0;
	colSize = 0;
	matrix = NULL;
}

Matrix::~Matrix()
{
	matrix = NULL;
}

Matrix::Matrix(const Matrix& original)
{
	name = original.name;
	rowSize = original.rowSize;
	colSize = original.colSize;
	for (int i = 0; i < original.rowSize; i++)
	{
		for (int j = 0; j < original.colSize; j++)
		{
			matrix[i][j] = original.matrix[i][j];
		}
	}
}

void Matrix::setRowSize(const int i)
{
	rowSize = i;
}

void Matrix::setColSize(const int j)
{
	colSize = j;
}

void Matrix::setName(const string name1)
{
	name = name1;
}

void Matrix::inputValues() // askes for each value individually
{
	matrix = new double*[rowSize];
	for (int i = 0; i < rowSize; ++i)
		matrix[i] = new double[colSize];

	for (int i = 0; i < rowSize; i++)
	{
		for (int j = 0; j < colSize; j++)
		{
			cout << "Please enter the value at possition " << i << ", " << j << "." << endl;
			cin >> matrix[i][j];
		}
	}
}

void Matrix::print()
{
	cout << name << ":" << endl;

	for (int i = 0; i < rowSize; i++)
	{
		for (int j = 0; j < colSize; j++)
		{
			cout << matrix[i][j] << "  ";
		}
		cout << endl;
	}

}

Matrix& Matrix::operator=(const Matrix& original)
{
	//checking that the matricies are the same size
	if (rowSize != original.rowSize || colSize != original.colSize)
	{
		cout << " Cannot copy matricies!" << endl;
		//returns unchanged matrix
		return *this;
	}

	//copies all values of th Matrix class
	name = original.name;
	rowSize = original.rowSize;
	colSize = original.colSize;
	for (int i = 0; i < original.rowSize; i++)
	{
		for (int j = 0; j < original.colSize; j++)
		{
			matrix[i][j] = original.matrix[i][j];
		}
	}
	return *this;
}

Matrix& Matrix::operator*(const Matrix& original)
{
	Matrix *temp;
	//checks that the matricies can be multiplied
	if (colSize != original.rowSize)
	{
		cout << "Cannot multiply these matricies." << endl;
		return *this;
	}
	//multiplies the matrcies if they are able to be
	else if (rowSize == original.colSize)
	{
		temp->name = (name + "*" + original.name);
		temp->rowSize = original.colSize;
		temp->colSize = rowSize;

		temp->matrix = new double*[temp->rowSize];
		for (int i = 0; i < temp->rowSize; ++i)
			temp->matrix[i] = new double[temp->colSize];

		for (int i = 0; i < rowSize; ++i)
		{
			for (int j = 0; j < original.colSize; ++j)
			{
				temp->matrix[i][j] = 0;
				for (int k = 0; k < colSize; ++k)
				{
					temp->matrix[i][j] = temp->matrix[i][j] + (matrix[i][k] * original.matrix[k][j]);
				}
			}
		}
	}
	return *temp;
}
Last edited on May 22, 2016 at 10:35pm
May 22, 2016 at 8:37pm
Please edit your post and put your code in [code] tags.
May 23, 2016 at 12:13am
1
2
Matrix* temp;   // temp points to some arbitrary point in memory.
temp->name = (name + "*" + original.name);  // Some arbitrary point in memory is treated as if it is a valid Matrix object. 
May 23, 2016 at 12:46am
Thank you for the suggestion however I originally did not have temp as a pointer at first, but I then switched it to a pointer to try to figure out the problem and the problem persists.
May 23, 2016 at 2:09am
Then supplying the actual code that is causing the problem is surely recommended.

Edit: Looking over your code, there are quite a few potential problems. For instance:
Matrix m; m.print(); results in undefined behavior.
All copies are shallow. All memory allocated is leaked.
Last edited on May 23, 2016 at 2:15am
May 23, 2016 at 3:03am
I don't see how that would cause that problem.
May 23, 2016 at 3:47am
I don't see how that would cause that problem.

I left out a couple of things.

Undefined behavior:
1
2
3
4
Matrix m;
m.setRowSize(5);
m.setColSize(5);
m.print();


And.. you still have the code up there you say you're not using.
Last edited on May 23, 2016 at 3:48am
May 23, 2016 at 4:17am
I am using the pointers. I said I switched to then to see if it would help. I'm lazy and have no need to change it back. I'll try your suggestion in the morning. Thank you!
May 23, 2016 at 6:52am
I'm lazy and have no need to change it back.

Except that what you did with temp is completely wrong, and if you were having problems before, you added another problem.
May 24, 2016 at 2:16am
I'm sorry but I am still lost on how to fix this.
May 24, 2016 at 2:33am
At the very least fix the temp problem and supply the modified code that was causing you problems before you added another one. temp should not be a pointer and certainly not a pointer that is not initialized to anything before it's first use (and it's quite likely you ignored a compiler warning telling you this very thing.)
May 24, 2016 at 2:40am
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include"Matrix.h"

Matrix::Matrix()
{
	name = "";
	rowSize = 0;
	colSize = 0;
	matrix = NULL;
}

Matrix::~Matrix()
{
	matrix = NULL;
}

Matrix::Matrix(const Matrix& original)
{
	//copies all values of th Matrix class
	name = original.name;
	rowSize = original.rowSize;
	colSize = original.colSize;
	for (int i = 0; i < original.rowSize; i++)
	{
		for (int j = 0; j < original.colSize; j++)
		{
			matrix[i][j] = original.matrix[i][j];
		}
	}
}


void Matrix::setRowSize(const int i)
{
	rowSize = i;
}

void Matrix::setColSize(const int j)
{
	colSize = j;
}

void Matrix::setName(const string name1)
{
	name = name1;
}

void Matrix::inputValues() // askes for each value individually
{
	matrix = new double*[rowSize];
	for (int i = 0; i < rowSize; ++i)
		matrix[i] = new double[colSize];

	for (int i = 0; i < rowSize; i++)
	{
		for (int j = 0; j < colSize; j++)
		{
			cout << "Please enter the value at possition " << i << ", " << j << "." << endl;
			cin >> matrix[i][j];
		}
	}
}

void Matrix::print()
{
	cout << name << ":" << endl;

	for (int i = 0; i < rowSize; i++)
	{
		for (int j = 0; j < colSize; j++)
		{
			cout << matrix[i][j] << "  ";
		}
		cout << endl;
	}

}

Matrix& Matrix::operator=(const Matrix& original)
{
	//checking that the matricies are the same size
	if (rowSize != original.rowSize && colSize != original.colSize)
	{
		cout << " Cannot copy matricies!" << endl;
		//returns unchanged matrix
		return *this;
	}

	//copies all values of th Matrix class
	name = original.name;
	rowSize = original.rowSize;
	colSize = original.colSize;
	for (int i = 0; i < original.rowSize; i++)
	{
		for (int j = 0; j < original.colSize; j++)
		{
			matrix[i][j] = original.matrix[i][j];
		}
	}
	return *this;
}

Matrix& Matrix::operator*(const Matrix& original)
{
	Matrix temp;

	//checks that the matricies can be multiplied
	if (colSize != original.rowSize)
	{
		cout << "Cannot multiply these matricies." << endl;
		return *this;
	}

	//multiplies the matrcies if they are able to be
	temp.matrix = new double*[original.rowSize];
	for (int i = 0; i < original.rowSize; ++i)
		temp.matrix[i] = new double[rowSize];

	temp.setName("New Matrix");
	temp.setRowSize(original.colSize);
	temp.setColSize(rowSize);

	for (int i = 0; i < rowSize; ++i)
	{
		for (int j = 0; j < original.colSize; ++j)
		{
			temp.matrix[i][j] = 0;
			for (int k = 0; k < colSize; ++k)
			{
				temp.matrix[i][j] += (matrix[i][k] * original.matrix[k][j]);
			}
		}
	}
	return temp;
}


There is no compiler error. Everything works great until the * operator is called.
Last edited on May 24, 2016 at 2:42am
May 24, 2016 at 2:56am
There is no compiler error.

How 'bout compiler warnings? Any of those?

1>...\matrix.cpp(133): warning C4172: returning address of local variable or temporary: temp


You still have a problem with temp. It's a local variable and you're returning a reference to it.

Typically the multiplication operator would return a Matrix by value.
Last edited on May 24, 2016 at 2:57am
May 24, 2016 at 3:01am
Removing the reference gets rid of the warnings however it still crashes
May 24, 2016 at 3:10am
Returning by value means you bring the copy constructor into play... and your copy constructor has a serious problem. Perhaps you can look at it and tell me what matrix points to when it is first assigned to dereferenced?

[edit: assigned to => dereferenced. matrix is never assigned to in the copy constructor.]
Last edited on May 24, 2016 at 3:13am
May 24, 2016 at 3:15am
AAAAHHHHHH! Thank you so much for putting up with me! It works!!!
Topic archived. No new replies allowed.