# Thread: Dynamic Memory Problem

1. ## Dynamic Memory Problem

Alright so I have a class of Matrix which looks like
Code:
```class Matrix
{
private:
string _name;
int errorInput;
int  _row;
int  _col;
double ** _mat;
public:
//Constructors
Matrix();
Matrix(const Matrix &m);
//Deconstructor
~Matrix();
//swap for copy
void swap(Matrix& m);
//get functions for variables
string getName(void);
int getRow(void);
int getCol(void);
int getError(void);
//set functions for variables
void setName(string name);
//clear the matrix
void clear(void);
//transpose Matrix
Matrix transpose(void);
Matrix & Matrix::operator = (const Matrix & mMatrix);
friend std::istream& operator>>(std::istream &is, Matrix & mMatrix);
friend ostream& operator<<(ostream& os, const Matrix& dt);
const Matrix operator+(double adder) const;
const Matrix operator-(double subber) const;
const Matrix operator*(double multer) const;
const Matrix operator+(const Matrix &rhs) const;
const Matrix operator-(const Matrix &rhs) const;
const Matrix operator*(const Matrix &rhs) const;```
And whenever an instances destructor gets called I face heap errors such as

In non-debugging mode i get this
Code:
```HEAP CORRUPTION DETECTED: after normal block (#184) at 0x004E95A8.
CRT Detected that the application wrote to memory after the end of heap buffer```
This in debug mode. Says windows has triggered a break point and brings me to the function below.

Code:
```/***
*int _CrtIsValidHeapPointer() - verify pointer is from 'local' heap
*
*Purpose:
*       Verify pointer is not only a valid pointer but also that it is from
*       the 'local' heap. Pointers from another copy of the C runtime (even in the
*       same process) will be caught.
*
*Entry:
*       const void * pUserData     - pointer of interest
*
*Return:
*       TRUE - if valid and from local heap
*       FALSE otherwise
*
*******************************************************************************/
extern "C" _CRTIMP int __cdecl _CrtIsValidHeapPointer(
const void * pUserData
)
{
if (!pUserData)
return FALSE;

if (!_CrtIsValidPointer(pHdr(pUserData), sizeof(_CrtMemBlockHeader), FALSE))
return FALSE;

return HeapValidate( _crtheap, 0, pHdr(pUserData) );
}.```
Now I have done as much investigating possible, in the matter of the address that gets deleted.

Basically a flow chart of what happens is the following

Code:
```I call the clear function of a temp instance a matrix.
-> then in the clear function I use a copy and swap type of clear where I create
a new temp instance of matrix and swap that with with the current matrix's contents
which then when leaves calls the destructor of the temp instance which now holds
the old data.

-> in the destructor i go row by row and delete the pointer of each row and
then delete the head pointer. When i try to delete a row i get the errors.```
My destructor looks like

Code:
```Matrix::~Matrix()
{
for(int i = 0; i < _row; i++)
{
delete[] _mat[i];
}
delete[] _mat;
_mat = NULL;
}```
And my copy constructor looks like

Code:
```Matrix::Matrix(const Matrix &m)
{
int i,j;
_row = m._row;
_col = m._col;
_name = m._name;
errorInput = m.errorInput;
_mat = new double *[_row];
for(i=0;i<_row;i++)
{
_mat[i] = new double [_col];
for(j=0;j<_col;j++)
{
_mat[i][j] = m._mat[i][j];
}
}
}```
I have my destructor print out addresses before deleting them and they all check out to the data I want to get deleted. But for some reason I get those two errors. Thoughts?

2. Show your clear and operator= functions.

3. clear
Code:
```void Matrix::clear(void)
{
Matrix temp;
swap(temp);
}```
Assignment operator
Code:
```Matrix & Matrix::operator = (const Matrix& mMatrix)
{
Matrix temp(mMatrix);
swap(temp);

return *this;
}```
swap
Code:
```void Matrix::swap(Matrix& m)
{
//uses std::swap and swaps the current matrix's contents with the contents of the arg m  - 1 by 1
std::swap(_name, m._name);
std::swap(_row, m._row);
std::swap(_col, m._col);
std::swap(errorInput, m.errorInput);
std::swap(_mat,m._mat);
}```

4. The thing that is confusing me is that the right memory I want to delete is actually in the destructor. So I have no clue why delete[] won't work on it. Some more background info, is that I try clearing the temp instance after I push it into a vector for my list. Maybe that is a problem? But doesn't pushing it into a vector re dynamically allocate it in the list because thats the way std::vector's are set up.

5. Can't see anything yet. Can you post all the code? A runnable program?

6. Alright well the code is pretty long so cheers lol. But the program will not run in release mode at all. But when I comment out the destructors code, it works fine in debug mode with no debugging.
Code:
```#include "Matrix.h"

//default constructor
Matrix::Matrix()
{
_name = "";
_row = 0;
_col = 0;
_mat = NULL;
errorInput = 1;
}
//copy constructor call
Matrix::Matrix(const Matrix &m)
{
int i,j;
_row = m._row;
_col = m._col;
_name = m._name;
errorInput = m.errorInput;
_mat = new double *[_row];
for(i=0;i<_row;i++)
{
_mat[i] = new double [_col];
for(j=0;j<_col;j++)
{
_mat[i][j] = m._mat[i][j];
}
}
}
//destructor
Matrix::~Matrix()
{
for(int i = 0; i < _row; i++)
{
delete[] _mat[i];
}
delete[] _mat;
_mat = NULL;
}
//swap for the copy
void Matrix::swap(Matrix& m)
{
//uses std::swap and swaps the current matrix's contents with the contents of the arg m  - 1 by 1
std::swap(_name, m._name);
std::swap(_row, m._row);
std::swap(_col, m._col);
std::swap(errorInput, m.errorInput);
std::swap(_mat,m._mat);
}
//returns the name of a matrix
string Matrix::getName(void)
{
return _name;
}
//returns the number of rows
int Matrix::getRow(void)
{
return _row;
}
//returns the number of columns
int Matrix::getCol(void)
{
return _col;
}
//returns the error
int Matrix::getError(void)
{
return errorInput;
}
//clear the matrix by using the copy swap idiom and creating a blank temp and swapping it with the
//current matrixs data. then when exits destructor gets called to destroy temp (old data)
void Matrix::clear(void)
{
Matrix temp;
swap(temp);
}
//this sets the name of the string passed to matrixs name
void Matrix::setName(string name)
{
_name.clear();
_name = name;
}
//transpose a matrix uses the copy and swap idiom again by using a copy constructor to create a temp instance
//with the data of the current matrix and a default constructor for another.  Set the corresponding rows and columns
//by reversing the order from the current matrix. while using the same new double method and swapping at the end with the new data
Matrix Matrix::transpose(void)
{
Matrix temp1;
temp1._row = _col;
temp1._col = _row;
temp1._mat = new double *[temp1._row];
for(int i = 0; i < temp1._row; i++)
{
temp1._mat[i] = new double [temp1._col];
for(int j = 0; j < temp1._col; j++)
{
temp1._mat[i][j] = _mat[j][i];
}
}
return temp1;
}
//sets the data of a matrix given a matrix operator overloading
//assignment operator just another copy and swap
Matrix & Matrix::operator = (const Matrix& mMatrix)
{
Matrix temp(mMatrix);
swap(temp);

return *this;
}
//overloaded input stream operator
std::istream& operator>>(std::istream &is, Matrix & mMatrix)
{
string tempString,restOfLine;
istringstream tempNumString;
deque<string> sList;
int row = 0;
int col = 0;
int foundEnd = 0;
int lastCol = 0;
double tempDBL;
//set flags for ios
std::ios_base::fmtflags temp=is.flags();
//get the entire line of input
getline(cin,restOfLine);
for(string::iterator sIT = restOfLine.begin(); sIT != restOfLine.end(); ++sIT)
{
//should only be one [ and it should be at the beginning
if(*sIT == '[')
{
//error if the [ is not at the begining of the line and thats it
if(sIT != restOfLine.begin())
{
mMatrix.errorInput = 3;
return is;
}
}
//the character is an ] then this is the final go around
else if(*sIT == ']')
{
if(tempString.size() > 0)
{
sList.push_back(tempString);
tempString.clear();
col++;
//check col
if(lastCol == 0)
{
lastCol = col;
row++;
}
else if(lastCol == col)
{
row++;
}
else
{
mMatrix.errorInput = 2;
return is;
}
}
else
{
//check col
if(lastCol == 0)
{
lastCol = col;
row++;
}
else if(lastCol == col)
{
row++;
}
else
{
mMatrix.errorInput = 2;
return is;
}
}
foundEnd = 1;
}
else if(*sIT == ';')
{
if(tempString.size() > 0)
{
sList.push_back(tempString);
tempString.clear();
col++;
//check col
if(lastCol == 0)
{
lastCol = col;
row++;
col = 0;
}
else if(lastCol == col)
{
row++;
col = 0;
}
else
{
mMatrix.errorInput = 2;
return is;
}
}
else
{
//check col
if(lastCol == 0)
{
lastCol = col;
row++;
col = 0;
}
else if(lastCol == col)
{
row++;
col = 0;
}
else
{
mMatrix.errorInput = 2;
return is;
}
}
}
//if find whitespace then gotta do a new column case if there is something in tempString
else if(*sIT == ' ')
{
if(tempString.size() > 0)
{
sList.push_back(tempString);
tempString.clear();
col++;
}
else
{
//then junk or just did above so skip over everything
}
}
//then the chacter must be something other than  '['	']'		';'		' '
else
{
//if it is a valid number then push it into a string
if(*sIT > 47 && *sIT < 58)
{
tempString.push_back(*sIT);
}
//if its not a valid number then leave
//and return proper error
else
{
mMatrix.errorInput = 3;
return is;
}
}
}
mMatrix.errorInput = 1;
mMatrix._row = row;
mMatrix._col = col;
//and do a final assignment to the matrix passed to the stream
mMatrix._mat = new double *[row-1];
for(int i=0;i<row;i++)
{
mMatrix._mat[i] = new double [col-1];
for(int j=0;j<col;j++)
{
//use isstringstreams to convert the string to a double
tempNumString.str(sList.front());
tempNumString >> tempDBL;
//then pop front to get the next string in line
sList.pop_front();
//clear the isstrinstream
tempNumString.clear();
//and finally assign the matrix its value
mMatrix._mat[i][j] = tempDBL;
}
}
is.flags(temp);
return is;
}
//overloaded operator for cout
//just a simple display loop
ostream& operator<<(ostream& os, const Matrix& m)
{
std::ios_base::fmtflags temp=os.flags();
int i,j;
cout << m._name << " =" << endl << endl;
for(i=0;i<m._row;i++)
{
for(j=0;j<m._col;j++)
{
cout << "\t" << m._mat[i][j];
}
cout << endl;
}
cout << endl << endl;
os.flags(temp);
return os;
}
//simple scalar addition with a matrix
const Matrix Matrix::operator+ (double adder)const
{
Matrix result(*this);
for(int i = 0; i < _row; i++)
{
for(int j = 0; j < _col; j++)
{
}
}
return result;
}
//simple scalar subtraction with a matrix
const Matrix Matrix::operator- (double subber)const
{
Matrix result(*this);
for(int i = 0; i < _row; i++)
{
for(int j = 0; j < _col; j++)
{
result._mat[i][j] -= subber;
}
}
return result;
}
//simple scalar multiplication with a matrix
const Matrix Matrix::operator* (double multer)const
{
Matrix result(*this);
for(int i = 0; i < _row; i++)
{
for(int j = 0; j < _col; j++)
{
result._mat[i][j] *= multer;
}
}
return result;
}
//addition between two matrices the rows and columns of each must equal
//then add term by term
const Matrix Matrix::operator+(const Matrix &rhs) const
{
Matrix result(*this);
if(_row == rhs._row && _col == rhs._col)
{
for(int i = 0; i< _row; i++)
{
for(int j = 0 ; j<_col ; j++)
{
result._mat[i][j] += rhs._mat[i][j];
}
}
}
return result;
}
//subtraction between two matrices the rows and columns of each must equal
//then subtract term by term
const Matrix Matrix::operator-(const Matrix &rhs) const
{
Matrix result(*this);
if(_row == rhs._row && _col == rhs._col)
{
for(int i = 0; i< _row; i++)
{
for(int j = 0 ; j<_col ; j++)
{
result._mat[i][j] -= rhs._mat[i][j];
}
}
}
return result;
}
//multiplactions between two matrices the new size of the matrix
//will be the rows of the first matrix by the columns of the second matrix
//and do the special math for each term (result._mat[i][j] = result._mat[i][j] + _mat[i][k] * rhs._mat[k][j])
const Matrix Matrix::operator*(const Matrix &rhs) const
{
Matrix result;
result._mat = new double*[_row];
for(int i=0;i<_row;i++)
{
result._mat[i] = new double [rhs._col];
for(int j=0;j<rhs._col;j++)
{
result._mat[i][j] = 0;
for(int k=0;k< _col;k++)
{
result._mat[i][j] = result._mat[i][j] + _mat[i][k] * rhs._mat[k][j];
}
}
}
//then set the new rows to the final matrix along with the cols
//and its errorinput to a 1
result._row = _row;
result._col = rhs._col;
result.errorInput = 1;
return result;
}```
main.cpp

Code:
```#include "Matrix.h"
/* THE FOLLOWING TWO FUNCTIONS MUST BE COMPLETED; THEY ARE LISTED AT THE BOTTOM OF THIS FILE */
// Finds matrix with name n in vector mL; returns -1 if matrix is not present
int findMatrix(vector <Matrix> &mL, string n);
// Adds matrix m to vector mL; returns position where added
int addMatrix(vector <Matrix> &mL, Matrix &m);

int main()
{
//definitions
vector <Matrix> mList;					// List of variables in program
string cmd, cmd2, cmd3;					// Strings for command input
string restOfLine, tempString;			// Used to clear input stream on errors
char c;									// Holds single input character
Matrix temp;							// Temporary matrix object
int pos, pos2, pos3;					// Used to hold position of matrices in mList
char op;								// Operator
int scalar;								// Scalar input variable

//forever while loop
while (1)
{
//display indicator
//and scan in the first thing should be a name of a matrix or cmd of exit clear who or whos
cout << ">> ";
cin >> cmd;

if (cmd == "exit")				// Exit program
return 0;

else if (cmd == "clear")		// Clear all variables
mList.clear();

else if (cmd == "who")
{
if(mList.size() > 0)
{
// Print variable names
cout << "Your variables are:" << endl << endl;
for(vector<Matrix>::iterator iT = mList.begin(); iT != mList.end(); ++iT)
{
cout << iT->getName() << "\t";
}
cout << endl << endl;
}
}
else if (cmd == "whos")
{
if(mList.size() > 0)
{
// Print detailed variable information
cout << "Name\tSize\tBytes" << endl << endl;
for(vector<Matrix>::iterator iT = mList.begin(); iT != mList.end(); ++iT)
{
cout << iT->getName() << "\t" << iT->getRow() << "x" << iT->getCol() << "\t" << (int)iT->getRow() * (int)iT->getCol() * 8 << " bytes" << endl << endl;
}
}
}

/* If no conditions above are true, treat cmd as name of matrix
* Possible commands include:
*  M = [<list>]	Create new matrix
*  M = M			Assign one matrix to another
*  M = M'			Assign the transpose of one matrix to another
*  M = -M			Assign the negative of one matrix to another
*  M = M op M		Perform op (+, -, *) on two matrices and assign result to matrix
*  M = M op S		Perform op (+, -, *) on matrix and scalar and assign result to matrix */
else
{

// cmd should be treated as matrix name--see if it's in mList
// Will use value of pos later
pos = findMatrix(mList, cmd);
//if following the name of matrix is a new line then print contents of the matrix
if (cin.peek() == '\n')
{
// End of line--should print contents of current matrix
if (pos == -1)
cerr << "Error: undefined matrix " << cmd << endl;
// Matrix found--print it
else
cout << mList[pos];
}
//if not new line character then the next charcter must be an = by itself
else
{
cin >> c;
if (c != '=')
{
// Wrong character--print error and clear input stream
cerr << "Error: incorrectly formatted command" << endl;
getline(cin, restOfLine);
}
else
{
/* How you handle the next part of the input depends on whether the
* first character is '[' or not--if it is, you're creating a new
* matrix (or assigning new values to an existing one); if it's not,
* then you're doing some sort of matrix operation. The >> operator
* will assume that you're reading in everything starting with the '[',
* so the code below will scan the input and discard all whitespace
* characters. You can't just use "cin >>" because you don't know
* what the next character will be. */

//skip the whitespace between the = and what follows
while ((c = cin.peek()) == ' ')
cin.get(c);

// Check for '[' --> assigning new values to matrix
if (c == '[')
{
//if the matrix name is not found on the left of = then
//must create the matrix parse the info from the [...] and use addMatrix to assign matrix
//to the list
if (pos == -1)
{
//clear all the leftover contents of temp
temp.clear();
//call the istream operator to parse what follows in the [...]
cin >> temp;
//upon return from the istream overloaded operator
//switch for errors
switch(temp.getError())
{
//if error is a 2 then the dimensions within the matrix are not the same
case 2:
temp.clear();
cout << "Dimensions don't match" << endl;

break;
//if error is a 3 then the matrix is missing the ]
case 3:
temp.clear();
cout << "Improperly formatted matrix" << endl;

break;
//if error is a 4 then the matrix has a character in it   [..a; 1 2 a]
case 4:
temp.clear();
cout << "Improperly formatted matrix" << endl;

break;
//if none above then the no error and good to set the name of the matrix to that
//from cmd which holds the name left of =
//then add instance of matrix to list and display it
default:
temp.setName(cmd);
cout << temp;
break;
}

}
else
{
//same as above except the name of matrix to left of = was found
//so only thing that changes is the default case which sets the matrix appropriate
//index in list to the temp instance
cin >> temp;
switch(temp.getError())
{
case 2:
temp.clear();
cout << "Dimensions don't match" << endl;

break;
case 3:
temp.clear();
cout << "Improperly formatted matrix" << endl;

break;
case 4:
temp.clear();
cout << "Improperly formatted matrix" << endl;

break;
default:
temp.setName(cmd);
mList.erase(mList.begin() + pos);
cout << temp;
break;
}
}
}

// Other commands of form M = expression
else
{
cin >> cmd2;	// Read matrix name

/* End of line--command must be:
*  M = M			Assign one matrix to another
*  M = M'			Assign the transpose of one matrix to another
*  M = -M			Assign the negative of one matrix to another */
if (cin.peek() == '\n')
{
// Transpose if find ' in the following string
if (cmd2.find('\'', cmd2.size() - 1) != string::npos)
{
//get the name of matrix to traspose by itself
cmd2 = cmd2.substr(0, cmd2.size() - 1);
//find its index in list
pos2 = findMatrix(mList, cmd2);
//if matrix on right of = doesnt exist then return error
if (pos2 == -1)
cerr << "Error: undefined matrix " << cmd2 << endl;
else
{
//if the matrix on right was found then
//clear the temp instance and set it to the transposed
//matrix of the index from the list
temp.clear();
temp = mList[pos2].transpose();
//set the name of the matrix to the name on the left
temp.setName(cmd);
//if matrix on left is not found then add new matrix
if(findMatrix(mList,cmd) == -1)
{
cout << temp;
}
//else set the index from list to the new temp instance
else
{
mList.erase(mList.begin() + pos);
cout << temp;
}
}
}

// Negative
else if (cmd2.find('-') == 0)
{
//find the matrix name following the first character which should be the -
cmd2 = cmd2.substr(1);
pos2 = findMatrix(mList, cmd2);
//if the matrix does not exist then error otherwise
//set the matrix on left of = to the - of the matrix on right
if (pos2 == -1)
cerr << "Error: undefined matrix " << cmd2 << endl;
else
{
//if matrix on left is not found then add new matrix
//with the appropriate neg data
if(findMatrix(mList,cmd) == -1)
{
temp.clear();
temp = mList[pos2] * (-1);
temp.setName(cmd);
cout << temp;
}
//else set the index from list to the right matrix * -1
else
{
temp = mList[pos2] * (-1);
temp.setName(cmd);
mList.erase(mList.begin() + pos);
cout << temp;
}
}
}
// Basic assignment
else
{
pos2 = findMatrix(mList, cmd2);
//if the matrix on the right is not found
//then return error otherwise set matrix on left to right
if (pos2 == -1)
cerr << "Error: undefined matrix " << cmd2 << endl;
else
{
//if matrix on left is not found then add new matrix
//by clearing temp and then add matrix with the appropriate data
if(findMatrix(mList,cmd) == -1)
{
temp.clear();
temp = mList[pos2];
temp.setName(cmd);
cout << temp;
}
//else set the index from list to the right matrix
else
{
temp = mList[pos2];
temp.setName(cmd);
mList.erase(mList.begin() + pos);
cout << temp;
}
}
}
}

/* Command must take one of two forms:
*  M = M op M		Perform op (+, -, *) on two matrices and assign result to matrix
*  M = M op S		Perform op (+, -, *) on matrix and scalar and assign result to matrix */
else
{
cin >> op;		// Read operator

/* Remove whitespace--need to be able to check if next string
is matrix or scalar */
while ((c = cin.peek()) == ' ')
cin.get(c);

// Scalar input--command is M op S
// Must fix name in each case when done
if ((c >= '0') && (c <= '9'))
{
//get the following number following the op
cin >> scalar;
//find if the matrix on the right of the = which has an op and scalar to it
//exists if it doesn return error if it does exist figure of what the op is and do according
pos2 = findMatrix(mList, cmd2);
if (pos2 == -1)
cerr << "Error: undefined matrix " << cmd2 << endl;
else
{
//switch for the op code
switch (op)
{
//if the op is + then a simple scalar addition is required
case '+':
//if matrix on left is not found then add new matrix
//with the appropriate data from addition of scalar
if(findMatrix(mList,cmd) == -1)
{
temp.clear();
temp = mList[pos2] + scalar;
temp.setName(cmd);
cout << temp;
}
//else set the index from list to the right matrix + scalar
else
{
temp.clear();
temp = mList[pos2] + scalar;
temp.setName(cmd);
mList.erase(mList.begin() + pos);
cout << temp;
}
break;
//simple subtraction of scalar and matrix
case '-':
//if matrix on left is not found then add new matrix
//with the appropriate data from subtraction of scalar
if(findMatrix(mList,cmd) == -1)
{
temp.clear();
temp = mList[pos2] - scalar;
temp.setName(cmd);
cout << temp;
}
//else set the index from list to the right matrix - scalar
else
{
temp.clear();
temp = mList[pos2] - scalar;
temp.setName(cmd);
mList.erase(mList.begin() + pos);
cout << temp;
}
break;
case '*':
//if matrix on left is not found then add new matrix
//with the appropriate data multiplied by scalar
if(findMatrix(mList,cmd) == -1)
{
temp.clear();
temp = mList[pos2] * scalar;
temp.setName(cmd);
cout << temp;
}
//else set the index from list to the right matrix * scalar
else
{
temp.clear();
temp = mList[pos2] * scalar;
temp.setName(cmd);
mList.erase(mList.begin() + pos);
cout << temp;
}
break;
default:
cerr << "Error: undefined operation " << op << endl;
}
}
}

// Matrix input--command is M op M
else {
cin >> cmd3;
//scanned in the 3rd matrix name time to check both matrices on right of = exist
//if matrix before op doesnt exit return error otherwise check other matrix
pos2 = findMatrix(mList, cmd2);
if (pos2 == -1)
cerr << "Error: undefined matrix " << cmd2 << endl;
else
{
//if matrix on right of op doesnt exist then return error
//otherwise both exist time to do the math
pos3 = findMatrix(mList, cmd3);
if (pos3 == -1)
cerr << "Error: undefined matrix " << cmd3 << endl;
else
{
//switch statement for the op between the two matrices
switch(op)
{
//addition of the two matrices requires them to be the same exact size
case '+':
if(mList[pos2].getCol() == mList[pos3].getCol() && mList[pos2].getRow() == mList[pos3].getRow())
{
//if the matrices are the same size then do the apporpiate math for the matrix
//on the left of the = and find out if it exists or not
if(findMatrix(mList,cmd) == -1)
{
temp.clear();
temp = mList[pos2] + mList[pos3];
temp.setName(cmd);
cout << temp;
}
//else set the index from list to the right matrix + 2nd right matrix
else
{
temp.clear();
temp = mList[pos2] + mList[pos3];
temp.setName(cmd);
mList.erase(mList.begin() + pos);
cout << temp;
}
}
else
cout << "Error: dimensions are inconsistent" << endl;
break;
case '-':
if(mList[pos2].getCol() == mList[pos3].getCol() && mList[pos2].getRow() == mList[pos3].getRow())
{
//if the matrices are the same size then do the apporpiate math for the matrix
//on the left of the = and find out if it exists or not
if(findMatrix(mList,cmd) == -1)
{
temp.clear();
temp = mList[pos2] - mList[pos3];
temp.setName(cmd);
cout << temp;
}
//else set the index from list to the right matrix - 2nd right matrix
else
{
temp.clear();
temp = mList[pos2] - mList[pos3];
temp.setName(cmd);
mList.erase(mList.begin() + pos);
cout << temp;
}
}
else
cout << "Error: dimensions are inconsistent" << endl;
break;
case '*':
//for matrix multiplication then the columns of the first matrix
//must equal the rows of the second matrix
if(mList[pos2].getCol() == mList[pos3].getRow())
{
//if the matrices are the appropriate size for matrix multiplication
//then do the apporpiate math for the matrix on the left of the = and find out if it exists or not
if(findMatrix(mList,cmd) == -1)
{
temp.clear();
temp = mList[pos2] * mList[pos3];
temp.setName(cmd);
cout << temp;
}
//else set the index from list to the right matrix * 2nd right matrix
else
{
temp.clear();
temp = mList[pos2] * mList[pos3];
temp.setName(cmd);
mList.erase(mList.begin() + pos);
cout << temp;
}
}
else
cout << "Error: inner dimensions must match" << endl;
break;
default:
cerr << "Error: undefined operation " << op << endl;
}
}
}
}
}
}
}
}
}
}
}

// Finds matrix with name n in vector mL; returns -1 if matrix not present
int findMatrix(vector <Matrix> &mL, string n)
{
for(vector<Matrix>::iterator iT = mL.begin(); iT != mL.end(); ++iT)
{
//if strings match use std function called distance to find the number of elements between
//the beginning of a vector and the current itereator pos
if(iT->getName() == n)
return (int)distance(mL.begin(), iT);
}
return -1;
}

// Add m to array of matrices
int addMatrix(vector <Matrix> &mL, Matrix &m)
{
mL.push_back(m);
Matrix tmp, tmp1;
for(long i=0;i<mL.size();i++)
{
for(long x=0; x<mL.size()-1-i; x++)
{
if(mL[x].getName() > mL[x+1].getName())
{
//r.push_back(rnd);
tmp = mL[x];
mL[x] =  mL[x+1];
mL[x+1] = tmp;
}
}
}
return -1;
}```

Code:
```#pragma once
#include <vector>
#include <string>
#include <sstream>
#include <deque>
#include <iostream>
#include <iomanip>
using namespace std;

class Matrix
{
private:
string _name;
int errorInput;
int  _row;
int  _col;
double ** _mat;
deque<string> mSList;
public:
//Constructors
Matrix();
Matrix(const Matrix &m);
//Deconstructor
~Matrix();
//swap for copy
void swap(Matrix& m);
//get functions for variables
string getName(void);
int getRow(void);
int getCol(void);
int getError(void);
//set functions for variables
void setName(string name);
//clear the matrix
void clear(void);
//transpose Matrix
Matrix transpose(void);
Matrix & Matrix::operator = (const Matrix & mMatrix);
friend std::istream& operator>>(std::istream &is, Matrix & mMatrix);
friend ostream& operator<<(ostream& os, const Matrix& dt);
const Matrix operator+(double adder) const;
const Matrix operator-(double subber) const;
const Matrix operator*(double multer) const;
const Matrix operator+(const Matrix &rhs) const;
const Matrix operator-(const Matrix &rhs) const;
const Matrix operator*(const Matrix &rhs) const;
};```

7. Ouch! Okay, I've got a copy of it running. You can delete the code above if you want to keep it secret. BTW, how do I enter a 2D matrix? I can enter
a = [1 2 3 4]
but not
a = [[1 2 3] [4 5 6]]

8. I could care less this is for school about the security of it . but for 2d then do a = [1 2 3 ; 1 2 3 ] the ; seperates rows

9. I feel like the problem resides somewhere within my list (vector of matrices). Something about local heap errors occur when I use things from the list.

But what doesn't make sense to me is that the way vectors are set up when you use push_back then doesn't that auto dynamically allocate the entire class. So that whatever I push into the vector will have different memory than the temp instance in main?

10. Is there a good reason why you're not using an std::vector or similar to manage the memory? Because as it stands you're code isn't exception-safe (not to mention that your problem at hand is most likely related to allocation). If there's some constraint preventing you from doing so I'd recommend that you implement your own vector class (a stripped-down version would suffice) to help simplify memory-management.

11. gardhr's right of course that it would be more normal and safer to use a vector to hold your data and let it handle the memory allocation/deallocation for you. And a list may be better for your list, instead of a vector. But if you want to keep it the way you have it I've noticed that your addMatrix is, at a minimum, inefficient. You could try something like this instead:
Code:
```void addMatrix(vector <Matrix> &mL, Matrix &m) {
for (vector<Matrix>::iterator it = mL.begin(); it != mL.end(); it++)
if (it->getName() > m.getName()) {
mL.insert(it, m);
return; // If it was inserted, then it's done.
}
mL.push_back(m); // If it wasn't inserted, then append to end of vector.
}```
I changed the return type to void since you weren't using the return value.

12. Yes this a lab for school, and requires that we learn dynamic memory allocation with raw pointers. It sucks because my professor barely covered anything related to the topic so I have been learning it through google and help from here.. But thanks I just don't see the problem, could you point out where the code isn't exception safe.

13. Nevermind I FIGURED IT OUT!! I've have spent countless hours staring at the code. And I feel like an idiot that I didn't even try changing this the code for my copy constructor is

Code:
```//copy constructor call
Matrix::Matrix(const Matrix &m)
{
int i,j;
_row = m._row;
_col = m._col;
_name = m._name;
errorInput = m.errorInput;
_mat = new double *[_row];
for(i=0;i<_row;i++)
{
_mat[i] = new double [_col];
for(j=0;j<_col;j++)
{
_mat[i][j] = m._mat[i][j];
}
}
}```
and the code when i parse a string is... All i needed to do was get rid of those -1's. hahahaha
Code:
```//and do a final assignment to the matrix passed to the stream
mMatrix._mat = new double *[row-1];
for(int i=0;i<row;i++)
{
mMatrix._mat[i] = new double [col-1];
for(int j=0;j<col;j++)
{
//use isstringstreams to convert the string to a double
tempNumString.str(sList.front());
tempNumString >> tempDBL;
//then pop front to get the next string in line
sList.pop_front();
//clear the isstrinstream
tempNumString.clear();
//and finally assign the matrix its value
mMatrix._mat[i][j] = tempDBL;
}
}```

14. Originally Posted by omGeeK
Yes this a lab for school, and requires that we learn dynamic memory allocation with raw pointers. It sucks because my professor barely covered anything related to the topic so I have been learning it through google and help from here.. But thanks I just don't see the problem, could you point out where the code isn't exception safe.
Basically, whenever you assign an allocation to a raw pointer (except where explicitly "guarded" by a destructor) you're writing exception unsafe code! That is, if an exception gets propagated within the scope of that function, there is no mechanism in place whatsoever to free up the memory. For that reason, the use of a smart pointers/containers is ABSOLUTELY MANDATORY in such cases. Failing to realize the importance of this concept (RAII) will only serve to cause you innumerable headaches in the future, so you'd best commit yourself to it once and for all right now. While you're at it, pass the idea along to everyone you know...including that numb-skull professor of yours!

15. One more important point: This isn't simply a memory leak issue. Consider a situation where you're allocating an object that writes data to a very fragile file; failing to deallocate it properly could well result in a corrupt file! Yes, RAII should be taken very seriously indeed...

Popular pages Recent additions