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;
}
Related
I have a flight class which has bool** property in it.
class Flight {
public:
int flightNumber;
int row;
int seat;
bool** seatReserv;
Flight();
Flight(int fly,int rw,int st);
~Flight();
Flight(const Flight& rightVal);
Flight& operator=(const Flight& rightVal);
};
I tried to write my overloaded assignment operator as below, however i realised that even i change my row and seat property, i am not changing the 2D arrays [row] and [seat] size.
Flight& Flight::operator=(const Flight& rightVal){
if(this != &rightVal){
for(int i = 0; i < row; i++){
delete[] this->seatReserv[i];
}
delete [] this->seatReserv;
flightNumber = rightVal.flightNumber;
row = rightVal.row;
seat = rightVal.seat;
this -> seatReserv = new bool*[row];
for(int i = 0; i < row; i++){
seatReserv[i] = new bool[seat];
}
for(int i = 0; i < row; i++){
for(int j = 0; j < seat; j++){
seatReserv[i][j] = rightVal.seatReserv[i][j];
}
}
}
return *this;
}
Furthemore i encountered the same problem in my copy constructor below, so the question is how can i write copy constructor and overload my assignment operator for my class?
Flight::Flight(const Flight& rightVal){
flightNumber = rightVal.flightNumber;
row = rightVal.row;
seat = rightVal.seat;
for(int i = 0; i < row; i++){
for(int j = 0; j < seat; j++){
seatReserv[i][j] = rightVal.seatReserv[i][j];
}
}
}
EDIT:I can not use vectors this is for a homework assignment so vector using is forbidden.
This would probably work as copy constructor:
Flight::Flight(const Flight &rightVal){
this->flightNumber = rightVal.flightNumber;
this->row = rightVal.row;
this->seat = rightVal.seat;
this->seatReserv = new bool*[row];
for (int i = 0; i < this->row; i++){
this->seatReserv[i] = new bool[seat];
for (int j = 0; j < this->seat; j++){
this->seatReserv[i][j] = rightVal.seatReserv[i][j];
}
}
}
For the = operator you could probably use the same thing as above, but don't forget to delete what was there before using the destructor (this is to avoid memory leaks).
Flight::~Flight(){
if (seatReserv == nullptr) return; //this means that at the beginning of the class seatReserv should be set to nullptr.
for (int i = 0; i < this->row; i++){
delete[] seatReserv[i];
}
delete[] seatReserv;
}
I also suggest that instead of using a "2D array", you use one single sequence of bools, with length row * seat. To access one at a specific place you'd do this:
i * row + j, instead of this array[i][j].
This is faster when allocating and freeing and it's more efficient for your CPU cache.
This
this -> seatReserv = new bool*[row];
for(int i = 0; i < row; i++){
seatReserv[i] = new bool[i];
}
should be this
this -> seatReserv = new bool*[row];
for(int i = 0; i < row; i++){
seatReserv[i] = new bool[seat];
}
The little details matter.
Your copy constructor doesn't allocate any memory for your 2D array, so that's a problem.
#include <iostream>
using namespace std;
class Matrix {
public:
long int **Matr;
long int n;
void Create() {
Matr = new long int *[n];
for (int z = 0; z < n; z++)
Matr[z] = new long int[n];
}
// constructors and destructor
Matrix() : n(5) { Create(); }
Matrix(long int i) : n(i) { Create(); }
// Copy constructor
Matrix(Matrix &N) {
n = N.n;
Matr = new long int *[n];
for (int i = 0; i < n; i++)
Matr[i] = new long int[n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
Matr[i][j] = N.Matr[i][j];
}
}
}
Matrix operator*(Matrix &mx) {
int i, j, k, num;
Matrix result(n);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
num = 0;
for (int k = 0; k < n; k++) {
num += Matr[i][k] * mx.Matr[k][j];
}
result.Matr[i][j] = num;
return result;
}
~Matrix() {
for (int z = 0; z < n; z++) {
delete[] Matr[z];
}
delete[] Matr;
}
void Display() {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cout << Matr[i][j];
}
cout << endl;
}
}
Matrix operator+(Matrix &mx) {
Matrix result(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
result.Matr[i][j] = Matr[i][j] + mx.Matr[i][j];
// cout << result.Matr[i][j] << "\n";
}
}
return result;
}
};
int main() {
Matrix M(2);
M.Matr[0][0] = 0;
M.Matr[0][1] = 1;
M.Matr[1][0] = 2;
M.Matr[1][1] = 3;
Matrix N(2);
N.Matr[0][0] = 0;
N.Matr[0][1] = 1;
N.Matr[1][0] = 2;
N.Matr[1][1] = 3;
Matrix C;
C = M + N;
cout << C.Matr[0][0];
return 0;
}
I am doing a Matrix OOP class with some basic methods. I can't do "+" operator work in the way I want. In this case, when I'm trying to print C.Matr[0][0] it's printing random number for some reason, but if I simply remove destructor from code it works as expected and printing 0. Can someone help me to figure out why this is happening? Thanks a lot.
C is assigned a temporary with a shared Matr. The temporary dies immediately and you delete dangling pointers in the dtor.
The rule of three/five/zero will help you to prevent it.
What you are missing a copy assignment operator:
Matrix& operator=(const Matrix& N)
{
// copy to temporary matrix
long int tmpN = N.n;
long int** tmpMatr = new long int*[tmpN];
for (int i = 0; i < tmpN; i++)
tmpMatr[i] = new long int[tmpN];
for (int i = 0; i < tmpN; i++)
{
for (int j = 0; j < tmpN; j++)
tmpMatr[i][j] = N.Matr[i][j];
}
// swap
long int** swapMatr = Matr;
long int swapN = n;
Matr = tmpMatr;
n = N.n;
// deallocate old Matr
for (int z = 0; z<swapN; z++){
delete[] swapMatr[z];
}
delete[] swapMatr;
return *this;
}
Online gdb
You must implement the assignment operator, not just the copy constructor and destructor.
The simplest way to implement the assignment operator is to use the copy / swap idiom:
#include <algorithm>
//...
class Matrix
{
//...
int **Matr;
int n;
//...
public:
Matrix& operator=(const Matrix& m)
{
if ( this != &m )
{
Matrix temp(m); // create a copy of the passed in value
std::swap(temp.Matr, Matr); // swap out the internals with *this
std::swap(temp.n, n);
} // Here temp's destructor removes the old memory that *this
// previously had
return *this;
}
//...
};
Note that this only works if you have a working, non-buggy copy constructor and destructor.
In addition, your copy constructor should be taking a const reference, not just a reference to Matrix:
Matrix(const Matrix& m) { ... }
Once you make those changes, the program no longer crashes, as seen here.
You don't have an assignment operator, so who knows what the line C = M + N; is doing?
Well, it's using the default assignment operator, which just copies each member in turn. In particular, the pointer Matr is copied from the pointer in the temporary M+N, so it points to memory which was allocated for the temporary, which is then destroyed.
Before you added the destructor, you had a memory leak, so the values persisted in the heap, and it appeared to work. After you added a destructor which freed the memory, it was apparently quickly overwritten.
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.
I have problem with calling delete inside functions. When I allocate memory using new inside function it seem do work, but deleting formerly allocated memory causes throwing of std::bad_alloc. Is it even possible, or can I only free memory under "a" from inside of main?
#include <iostream>
using namespace std;
int size = 5;
void alloc (int* t, char**& a) {
t = new int [size];
a = new char* [size];
for (int i = 0; i < size; ++i)
a[i] = new char [size];
cout << "allocated\n";
}
void realloc (char**& a) {
for(int i = 0; i < size; ++i)
delete [] a[i];
delete [] a;
cout << "deleted\n";
a = new char* [size];
for (int i = 0; i < size+5; ++i)
a[i] = new char [size+5];
cout << "allocated\n";
}
void fillArray (char** a) {
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
a[i][j] = '.';
}
}
}
void printArray (char** a) {
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
cout << a[i][j];
}
cout << endl;
}
}
int main() {
int* t;
char** a;
alloc(t, a);
fillArray(a);
printArray(a);
size+=5;
realloc(a);
fillArray(a);
printArray(a);
}
You can call delete[] from anywhere. Your problems are much more prosaic. You just have a defect in your code.
You allocate an array of length size. Then you increment size. Then you do this:
for(int i = 0; i < size; ++i)
delete [] a[i];
And because you incremented size already, your loop runs off the end of a. You need to use the same value for size as was used when you allocated the array.
To be quite clear, the following is the flow of execution:
size is assigned to the value 5.
a is allocated with length 5.
size is incremented to the value 10.
You run a for loop from 0 to size-1, that is 0 to 9, and call delete[] a[i].
Clearly the iterations 5 to 9 inclusive are accessing elements of a that were not allocated. And that's undefined behaviour, and so on.
You could fix this by passing the new size to the realloc function as a parameter. Something like this:
void realloc (char**& a, size_t newsize) {
for(int i = 0; i < size; ++i)
delete [] a[i];
delete [] a;
size = newsize;
a = new char* [size];
for (int i = 0; i < size; ++i)
a[i] = new char [size];
}
Obviously you would not modify size outside of this function. You would call the function like this:
realloc(a, size+5);
Taking it a bit further, you might choose to handle the allocations like this:
size_t size = 5;
void alloc(char**& a, size_t newsize) {
size = newsize;
a = new char*[size];
for (int i = 0; i < size; ++i)
a[i] = new char[size];
}
void realloc(char**& a, size_t newsize) {
for(int i = 0; i < size; ++i)
delete[] a[i];
delete[] a;
alloc(a, size+5);
}
All that said, and being perfectly frank, your entire program is a disaster in the making. There are many other errors that I've not covered in this answer. Use standard containers like std::vector and std::string. The standard containers will handle the details of memory allocation, and will do it correctly.
What am I doing wrong? I allocated using new but when i try to delete[] it gives me an error.
mycode:
int** ma;
int n;
int m;
m = nr_col_lin;
n = nr_col_lin;
ma = new int*[m];
for(i = 0; i < m; i++)
ma[i] = new int[n];
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
ma[i][j] = 0;
}
}
and the dealocation:
for(int i = 0; i < m; ++i)
delete[] ma[i];
delete [] ma;
EDIT:
I found the problem... it wasn't in the code... I was deleting something I didn't allocate.
There is absolutely nothing wrong in your code. It is perfect. The probem must be somewhere else, assuming nr_col_lin is initialized with some valid value, i.e make sure it is not 0 or negative. If it is size_t or some unsigned integral value, then make sure m and n are greater than 0.