When I try to delete my pointers on distractor, my program is crashing, why?
I don't understand what I am doing wrong in my code.
Am I using new wrong?
class Matrix:
class Matrix
{
private:
double **_array;
int _rows, _cols;
...
Matrix::Matrix(int rows, int cols)
{
if (rows <= 0 || cols <= 0)
exit(-1);
this->_array = new double*[rows];
for (int i = 0; i < rows; i++)
this->_array[i] = new double[cols];
this->_rows = rows;
this->_cols = cols;
}
The problem is here:
void Matrix::pow(int power, Matrix& result)
{
/*if (result == NULL)
exit(-1);*/
if (result._cols != this->_cols || result._rows != this->_rows)
exit(-1);
// Can't pow the matrix, return mat of '0' values
if (this->_cols != this->_rows)
{
for (int i = 0; i < result._rows; i++)
for (int j = 0; j < result._cols; j++)
result.setElement(i, j, 0);
return;
}
/*if (power == 0)
result = 1;*/
double sum = 0;
Matrix temp(this->_rows, this->_cols);
// Copy this matrix to result matrix
for (int i = 0; i < this->_rows; i++)
for (int j = 0; j < this->_cols; j++)
result.setElement(i, j, this->_array[i][j]);
// Pow loop
for (int p = 1; p < power; p++)
{
for (int i = 0; i < this->_rows; i++)
for (int j = 0; j < this->_cols; j++)
{
for (int k = 0; k < this->_rows; k++)
sum += this->getElement(i, k) * result.getElement(k, j);
temp.setElement(i ,j ,sum);
sum = 0;
}
// Copy temp array to result array
for (int i = 0; i < this->_rows; i++)
for (int j = 0; j < this->_cols; j++)
result.setElement(i, j, temp.getElement(i, j));
for (int i = temp._rows; i >= 0; i--)
delete[] temp._array[i];
delete[] temp._array;
}
}
Main:
void main()
{
int rows = 3, cols = 3;
Matrix m1(rows, cols);
Matrix other(rows, cols);
Matrix result(rows, cols);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
{
m1.setElement(i, j, i + j);
other.setElement(i, j, 3 * (i + j + 1));
}
m1.pow(3, result);
}
SetElements:
void Matrix::setElement(int i, int j, double data)
{
if (i < 0 || j < 0)
exit(-1);
if (i >= this->_rows || j >= this->_cols)
exit(-1);
_array[i][j] = data;
}
thanks
1) The word for member function that prepares an object to no longer exist is destructor, not distractor.
2) If you the array form of operator new, using the non-array form of operator delete - which you are - gives undefined behaviour. Use the array form of operator delete instead.
3) Your code, as shown, uses other functions that you have no provided. Any of those, if implemented incorrectly, could be doing an invalid operation on a pointer, and therefore be OTHER causes of your crash.
4) Don't bother to use dynamic memory allocation (operator new, etc) to work with dynamically allocated arrays. You have demonstrated that doing so is error prone. If you want a dynamically allocated array of double use a std::vector<double>. If you want a two dimensional array of double, use a std::vector<std::vector<double> >. Apart from being less error prone, a std::vector releases its memory correctly (as long as you don't write some other code which trashes memory).
In your Matrix, you allocate new arrays:
...
this->_array = new double*[rows]; // <== array of pointers
for (int i = 0; i < rows; i++)
this->_array[i] = new double[cols]; // <== arrays of doubles
...
But in your destructor you delete elements. You have to correct this: Everytime you alocate an array (new []), you have to delete the array (delete []), or you'll get undefined behaviour (for example crash):
for (int i = 0; i < _rows; i++)
delete[] _array[i]; // <== delete array, not element!!
delete[] _array; // <== delete array, not element!!
Note: that everytime you're tempted to use new/delete, you should ask yourself, if it wouldn't be worth to consider using vectors instead. It's very easy as this online demo show with your code reworked
Edit: your problem with pow():
Here you create the matrix object temp:
Matrix temp(this->_rows, this->_cols);
This object will be destructed automatically at the end of the function pow(). THis means that its destructor will call all the necessary delete[].
The problem is that at the end of the function, you manually do the job of the destructor, so you delete[] temp's arrays. Then the destructor tries to delete already deleted objects. This is undefined behaviour and hence the crash !
All you have to do is get rid of the 3 last lines of pow() and the unnecessary delete[] they contain.
Related
When running the code I keep getting error "free(): double free detected in tcache 2". How can I not deallocate new instance array? Shouldn't it be deallocate at the moment I run the second instance? Why deallocate constructor doesn't work for the n instance? How can I solve this? Should I deallocate the arr of n manually in assignment operator?
#include <iostream>
#include <iomanip>
using namespace std;
class spMatrix{
private:
int N;
public:
double** arr;
spMatrix(): N(0), arr(NULL){};
spMatrix(int size): N(size){
N = size;
arr = new double* [size];
for(int i = 0; i < size; i++) arr[i] = new double [size];
};
//copy constructor
spMatrix(const spMatrix& original){
N = original.N;
arr = new double* [N];
for (int i = 0; i < N; ++i)
{
arr[i] = new double [N];
for (int j = 0; j < N; ++j)
{
arr[i][j] = original.arr[i][j];
}
}
}
~spMatrix(){
if(arr != NULL){
for (int i = 0; i < N; i++)
{
if (arr[i] != NULL) delete [] arr[i];
}
delete [] arr;
}
}
spMatrix& operator = (spMatrix const & other){
N = other.N;
arr = other.arr;
for(int i = 0; i < N; i++) {
arr[i] = other.arr[i];
for (int j = 0; j < N; j++){
arr[i][j] = other.arr[i][j];
}
}
return *this;
}
void show(){
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < N; ++j)
{
cout << arr[i][j] << " ";
}
cout << endl;
}
}
};
int main(int argc, char const *argv[])
{
spMatrix m(2);
spMatrix n(2);
m = n;
m.show();
return 0;
}
In your copy constructor:
N = other.N;
arr = other.arr;
for(int i = 0; i < N; i++) {
arr[i] = other.arr[i];
for (int j = 0; j < N + 1; j++){
arr[i][j] = other.arr[i][j];
}
}
return *this;
}
This only copies/duplicates the 2nd dimension of the 2D-matrix. The first dimension is not duplicated. Try to focus your attention on just the following line:
arr = other.arr;
If you think about this for a moment, it should be clear that you end up with two different objects having the same identical arr class member pointer. This is not correct. Different matrix objects should always be completely independent of each other and not share any pointers in common (at least not without reference-counting, and other complicated semantics).
You simply need to make a copy of arr, too. Everything else remains the same. It should probably be something like:
arr = new double* [N];
Looks like everything else can remain the same, note how this is identical to the same allocation in the regular constructor.
However the assignment operator has the same defect, but after understanding the problem in the copy constructor it should be clear how to fix it (same fix).
Your assignment operator also has a separate bug: it leaks memory. It needs to delete the entire 2D matrix in this, before cloning it from other.
Your problem is in the copy assignment operator:
spMatrix& operator = (spMatrix const & other){
N = other.N; // <<<A>>>
arr = other.arr; // <<<B>>>
for(int i = 0; i < N; i++) {
arr[i] = other.arr[i];
for (int j = 0; j < N + 1; j++){
arr[i][j] = other.arr[i][j];
}
}
return *this;
}
There are two significant and separate problems here. First, the current object owns some memory, an array of N arrays of length N.
However, after line <<>> you no longer know how many arrays you hold.
Second, after line <<>> you no longer know the address of your arrays, and so they are leaked.
Worse, line <<>> is also now pointing this object's array into other's memory, and both objects think they own that array. When one spMatrix destructor runs, the other will still point to it and use deleted memory. When the second one is destroyed, it'll be the second delete on the already deleted memory.
All of the copying you're trying to do in those for loops is not really doing anything, since you're assigning from and to the same address.
You must allocate new buffers before copying them, and not look at the address the other object has... because it's their memory not yours to take.
And you should keep the old pointers around, so that you can delete them after the allocations complete. That way if something fails you can still put it back, without messing your object up first. For example, the logic of line <<>> should be last, not first, only after everything succeeds.
I changed the assignment operator as below and it solved it.
spMatrix& operator = (spMatrix const & other){
N = other.N;
arr = new double* [N];
for(int i = 0; i < N; i++) {
arr[i] = new double[N];
for (int j = 0; j < N; j++){
arr[i][j] = other.arr[i][j];
}
}
return *this;
}
here is my question:
I have two classes Vector and Matrix, and I have define two functions, one to calculate the multiplication of a vector and a matrix and the other is to assign the value to a new vector.
Here is the code:
file: Matrix.cpp
Vector Matrix::operator*(const Vector& v)const {
assert(v.length == numRows);
Vector temp(v.length);
for (int j = 0; j < numCols; j++)
for (int k = 0; k < v.length; k++)
temp.contents[j] += v.contents[k] * contents[k][j];
return temp;
};
file: Vector.cpp
Vector& Vector::operator=(Vector& v){
assert(v.length == length);
if (&v != this) {
for (int i = 0; i < length; i++)
setComponent(i, v.contents[i]);
}
return *this;
};
Suppose I have well defined a 4*4 matrix m1 and a 1*4 vector v1
Here is part of my code in main() function,
file: main.app
Vector v2(4);
v2 = m1 * v1;
It can compile but will encounter a problem.
Can anyone give me a hint on how to deal with this? Is it because that I am trying to bind a reference with a return value of a function? Thanks so much!
In you code you defined the assignment operator like this Vector& Vector::operator=(Vector &v). But it should be like Vector& Vector::operator=(Vector const & v). The reason is that Vector &v refers to an lvalue reference. But m1 * v1 returns a rvalue.
Writing an address of 0x00....04 is an offset of 4 bytes from a null ptr. It means that you are trying to write through an uninitialized pointer. If you use a debugger, you can find the exact code trying to do this.
Be careful that you are not having name clash with std::vector.
Presume you have constructor, copy constructor (given below, also needed assignment operator) that allocates properly and initializes all elements to zero
Vector::Vector(int sz) {
contents = new int[length = sz]; // allocation
for (int i = 0; i < sz; i++) {
contents[i] = 0;
}
}
Vector::Vector(const Vector& v) {
contents = new int[length = v.length]; // allocation
for (int i = 0; i < length; i++) {
contents[i] = v.contents[i];
}
}
Matrix::Matrix(int rows, int cols) {
contents = new int *[numRows = rows]; // allocation
for (int i = 0; i < rows; i++) {
contents[i] = new int[numCols = cols]; // allocation
for (int j = 0; j < cols; j++) {
contents[i][j] = 0;
}
}
}
Matrix::Matrix(const Matrix& m) {
contents = new int *[numRows = m.numRows]; // allocation
for (int i = 0; i < numRows; i++) {
contents[i] = new int[numCols = m.numCols]; // allocation
for (int j = 0; j < numCols; j++) {
contents[i][j] = 0;
}
}
}
I have a question as follows:
I declared two pointer-to-pointer double-type variables **matrix1 and **matrix2 and allocate them by new operator to become 2D arrays.
First I used for loop to make matrix1 point to double-type data called element, then I copy matrix1 to matrix2, which means matrix2 points to element too. Then problem comes: I used delete operator to terminate matrix1 after copying, but then the values matrix2 point to became extremely strange. I think that was because after deleting matrix1, element terminates, so I think one of a solution is let matrix2 point to other address with the values same with element. But I don't know how to do this(copy element to new dynamic memories and won't disappear after deleting matrix1) in an efficient way, can somebody help me? thank you.
void MatCpy(double **InMat, double **OutMat, int NumOfRow, int NumOfCol)
{
for (int j = 0; j < NumOfRow; j++)
{
for (int i = 0; i < NumOfCol; i++)
{
OutMat[j][i] = InMat[j][i];
}
}
}
double **Malloc2D_Dbl(int row, int col)
{
double **data = new double*[row];
for (int i = 0; i < row; i++)
data[i] = new double[col];
return data;
}
void load(char *load_path, double **data, int height, int width) // function for loading
{
int i = 0, j = 0;
char buffer[30];
file_handle = fopen (load_path, "r");
for (int k = 0; k < width*height; k++)
{
fscanf (file_handle, "%s", &buffer);
j = k / width;
i = k % width;
data[j][i] = atof(buffer);
}
fclose (file_handle);
}
Sorry I am a noob....
More efficient than copying the individual elements is to use memcpy like this:
void MatCpy(double **InMat, double **OutMat, int NumOfRow, int NumOfCol) {
for(int j=0; j<NumOfRow; j++) {
memcpy(OutMat[j], InMat[j], NumOfCol*sizeof(double));
}
}
I keep getting the error Heap Corruption Detected. I have read through several questions on here, but I can't quite find out what is causing this in my code. I am trying to create a 2d array that will hold a matrix that is read from a text file.
// Create a 2d matrix to hold the matrix (i = rows, j = columns)
matrix = new int*[cols];
for(int i = 0; i <= cols; i++) {
matrix[i] = new int[rows];
}
// Populate the matrix from the text file
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
inputFile >> matrix[i][j];
}
}
My destructor is:
for(int i = 0; i <= cols; i++) {
delete[] matrix[i];
}
delete[] matrix;
I've tried debugging, but that does do much help in this case. Any suggestions?
matrix = new int*[cols];
for(int i = 0; i <= cols; i++) {
matrix[i] = new int[rows];
}
For an array with cols elements, the index is from 0 to cols - 1 inclusively.
The heap corruption will be detected when
delete [] matrix;
Since matrix[cols] write a position out of array bound.
UPDATE
As #DanielKO (thank you buddy :p) pointed out in the comment
there is a mismatch, the "Populate the matrix..." loop makes "i"
iterate over "rows" when it should be iterating over "cols".
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
inputFile >> matrix[i][j];
When you allocated you went from 0 to cols in i. Now you're changing i to be rows.
EDIT: Below would honor your commented row/column rules and follow RAII:
std::vector<std::vector<int>> matrix(rows, std::vector<int>(cols));
for( int i=0; i<rows; ++i ) {
for( int j=0; j<cols; ++j ) {
inputFile >> matrix[i][j];
}
}
// no need for delete matrix cleaned up when leaving scope.
Following this nice example I found, I was trying to create a function that dynamically generates a 2D grid (two dimensional array) of int values.
It works fairly well the first couple of times you change the values but if crashes after that. I guess the part where memory is freed doesn't work as it should.
void testApp::generate2DGrid() {
int i, j = 0;
// Delete previous 2D array
// (happens when previous value for cols and rows is 0)
if((numRowsPrev != 0) && (numColumnsPrev != 0)) {
for (i = 0; i < numRowsPrev; i++) {
delete [ ] Arr2D[i];
}
}
// Create a 2D array
Arr2D = new int * [numColumns];
for (i = 0; i < numColumns; i++) {
Arr2D[i] = new int[numRows];
}
// Assign a random values
for (i=0; i<numRows; i++) {
for (j = 0; j < numColumns; j++) {
Arr2D[i][j] = ofRandom(0, 10);
}
}
// Update previous value with new one
numRowsPrev = numRows;
numColumnsPrev = numColumns;
}
I see 1 major bug:
// Assign a random values
for (i=0; i<numRows; i++){
for (j=0; j<numColumns; j++){
Arr2D[i][j] = ofRandom(0, 10);
}
}
Here the variable 'i' is used as the first index into 'Arr2D' and goes to a max of (numRows -1)
While in this code:
for (i=0; i<numColumns; i++)
{
Arr2D[i] = new int[numRows];
}
The variable 'i' is used as the first index but goes to a max of (numColumns-1). If numRows is much larger than numColumns then we are going to have a problem.
As a side note. When you try and clean up you are leaking the columns:
if((numRowsPrev != 0) && (numColumnsPrev != 0))
{
for (i=0; i<numRowsPrev; i++){
delete [ ] Arr2D[i];
}
// Need to add this line:
delete [] Arr2D;
}
Next thing to note.
This is truly not a good idea. Use some of the provided STL classes (or potentially boost Matrix). This looks like you are binding global variables and all sorts of other nasty stuff.
2-dim array in C++ with no memory issues:
#include <vector>
typedef std::vector<int> Array;
typedef std::vector<Array> TwoDArray;
Usage:
TwoDArray Arr2D;
// Add rows
for (int i = 0; i < numRows; ++i) {
Arr2D.push_back(Array());
}
// Fill in test data
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numCols; j++) {
Arr2D[i].push_back(ofRandom(0, 10));
}
}
// Make sure the data is there
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numCols; j++) {
std::cout << Arr2D[i][j] << ' ';
}
std::cout << '\n';
}