Pointer being freed was not allocated when implementing Matrix<T> class - c++

I'm trying to build my own Matrix class and have overloaded the "*=" operator.
I am however running into problems with some pointer loss. I don't understand where my problem is at the moment.
Is it because I'm creating a new Matris "new_m" and this only lives inside the scope of the function? So I can't set the new pointer to data to the implied (*this) object?
Below is the code for my *= operator.
Matris<T> &operator*=(const Matris<T> &m){
//if(m_cols != m.m_rows || m.rows != m.m_cols) throw new std::out_of_range("When multiplying two matrices they have to have be \"opposites\", that is one can be 1x2 and other one 2x1.");
//else{
unsigned int new_cap = m_rows * m.m_cols;
Matris<T> new_m(sqrt(new_cap));
new_m.m_vec = (T*) realloc(new_m.m_vec, new_cap*sizeof(T));
std::memset (new_m.m_vec, 0, sizeof(T) * new_cap);
for(size_t i = 0; i < m_rows; i++){
for (size_t j = 0; j < m.m_cols; j++) {
for (size_t k = 0; k < m_cols; k++) {
new_m(i,j) += (*this)(i,k) * m(k,j);
}
}
}
m_vec = new_m.m_vec;
//}
return *this;
}
And this is how I store and save my data in my Matris class:
private:
size_t m_rows;
size_t m_cols;
size_t m_capacity;
T * m_vec;
This is the constructor that is being called with an int:
explicit Matris(const unsigned int i){ //constructor with one integer, has to be integer, can't be negative or float.
m_rows = i;
m_cols = i;
m_capacity = i*i;
m_vec = (T*) malloc(i*i*sizeof(T));
std::memset (m_vec, 0, sizeof (T) * i*i);
}

m_vec = new_m.m_vec;
This makes m_vec point to part of the temporary object that's about to be destroyed. You want:
*this = new_m;

Related

Operator Overloading Matrix Multiplication

The issue I am having is how to get the correct number columns to go through for the inner most loop of K.
An example is a 2x3 matrix and a 3x2 matrix being multiplied.
The result should be a 2x2 matrix, but currently I dont know how to send the value of 2 to the operator overloaded function.
It should be
int k = 0; k < columns of first matrix;k++
Matrix::Matrix(int row, int col)
{
rows = row;
cols = col;
cx = (float**)malloc(rows * sizeof(float*)); //initialize pointer to pointer matrix
for (int i = 0; i < rows; i++)
*(cx + i) = (float*)malloc(cols * sizeof(float));
}
Matrix Matrix::operator * (Matrix dx)
{
Matrix mult(rows, cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
mult.cx[i][j] = 0;
for (int k = 0; k < ?;k++) //?????????????
{
mult.cx[i][j] += cx[i][k] * dx.cx[k][j];
}
}
}
mult.print();
return mult;
//calling
Matrix mult(rowA, colB);
mult = mat1 * mat2;
}
Linear algebra rules say the result should have dimensions rows x dx.cols
Matrix Matrix::operator * (Matrix dx)
{
Matrix mult(rows, dx.cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
mult.cx[i][j] = 0;
for (int k = 0; k < cols;k++) //?????????????
{
mult.cx[i][j] += cx[i][k] * dx.cx[k][j];
}
}
}
mult.print();
return mult;
A few random hints:
Your code is basically C; it doesn’t use (e.g.) important memory-safety features from C++. (Operator overloading is the only C++-like feature in use.) I suggest that you take advantage of C++ a bit more.
Strictly avoid malloc() in C++. Use std::make_unique(...) or, if there is no other way, a raw new operator. (BTW, there is always another way.) In the latter case, make sure there is a destructor with a delete or delete[]. The use of malloc() in your snippet smells like a memory leak.
What can be const should be const. Initialize as many class members as possible in the constructor’s initializer list and make them const if appropriate. (For example, Matrix dimensions don’t change and should be const.)
When writing a container-like class (which a Matrix may be, in a sense), don’t restrict it to a single data type; your future self will thank you. (What if you need a double instead of a float? Is it going to be a one-liner edit or an all-nighter spent searching where a forgotten float eats away your precision?)
Here’s a quick and dirty runnable example showing matrix multiplication:
#include <cstddef>
#include <iomanip>
#include <iostream>
#include <memory>
namespace matrix {
using std::size_t;
template<typename Element>
class Matrix {
class Accessor {
public:
Accessor(const Matrix& mat, size_t m) : data_(&mat.data_[m * mat.n_]) {}
Element& operator [](size_t n) { return data_[n]; }
const Element& operator [](size_t n) const { return data_[n]; }
private:
Element *const data_;
};
public:
Matrix(size_t m, size_t n) : m_(m), n_(n),
data_(std::make_unique<Element[]>(m * n)) {}
Matrix(Matrix &&rv) : m_(rv.m_), n_(rv.n_), data_(std::move(rv.data_)) {}
Matrix operator *(const Matrix& right) {
Matrix result(m_, right.n_);
for (size_t i = 0; i < m_; ++i)
for (size_t j = 0; j < right.n_; ++j) {
result[i][j] = Element{};
for (size_t k = 0; k < n_; ++k) result[i][j] +=
(*this)[i][k] * right[k][j];
}
return result;
}
Accessor operator [](size_t m) { return Accessor(*this, m); }
const Accessor operator [](size_t m) const { return Accessor(*this, m); }
size_t m() const { return m_; }
size_t n() const { return n_; }
private:
const size_t m_;
const size_t n_;
std::unique_ptr<Element[]> data_;
};
template<typename Element>
std::ostream& operator <<(std::ostream &out, const Matrix<Element> &mat) {
for (size_t i = 0; i < mat.m(); ++i) {
for (size_t j = 0; j < mat.n(); ++j) out << std::setw(4) << mat[i][j];
out << std::endl;
}
return out;
}
} // namespace matrix
int main() {
matrix::Matrix<int> m22{2, 2};
m22[0][0] = 0; // TODO: std::initializer_list
m22[0][1] = 1;
m22[1][0] = 2;
m22[1][1] = 3;
matrix::Matrix<int> m23{2, 3};
m23[0][0] = 0; // TODO: std::initializer_list
m23[0][1] = 1;
m23[0][2] = 2;
m23[1][0] = 3;
m23[1][1] = 4;
m23[1][2] = 5;
matrix::Matrix<int> m32{3, 2};
m32[0][0] = 5; // TODO: std::initializer_list
m32[0][1] = 4;
m32[1][0] = 3;
m32[1][1] = 2;
m32[2][0] = 1;
m32[2][1] = 0;
std::cout << "Original:\n\n";
std::cout << m22 << std::endl << m23 << std::endl << m32 << std::endl;
std::cout << "Multiplied:\n\n";
std::cout << m22 * m22 << std::endl
<< m22 * m23 << std::endl
<< m32 * m22 << std::endl
<< m23 * m32 << std::endl
<< m32 * m23 << std::endl;
}
Possible improvements and other recommendations:
Add consistency checks. throw, for example, a std::invalid_argument when dimensions don’t match on multiplication, i.e. when m_ != right.n_, and a std::range_error when the operator [] gets an out-of-bounds argument. (The checks may be optional, activated (e.g.) for debugging using an if constexpr.)
Use a std::initializer_list or the like for initialization, so that you can have (e.g.) a const Matrix initialized in-line.
Always check your code using valgrind. (Tip: Buliding with -g lets valgrind print also the line numbers where something wrong happened (or where a relevant preceding (de)allocation had happened).)
The code could me made shorter and more elegant (not necessarily more efficient; compiler optimizations are magic nowadays) by not using operator [] everywhere and having some fun with pointer arithmetics instead.
Make the type system better, so that (e.g.) Matrix instances with different types can play well with each other. Perhaps a Matrix<int> multiplied by a Matrix<double> could yield a Matrix<double> etc. One could also support multiplication between a scalar value and a Matrix. Or between a Matrix and a std::array, std::vector etc.

how to have a copy constructor for vector?

I simulated a vector but the constructor doesn't work; when I call pop() function it assigns garbage value to my old object in vector class.
vector(vector &v) {
vec = new T[v.size()];
memcpy(vec, v,v.size());
size_arr = v.size();
}
here's entire code:
#include <iostream>
using namespace std;
template <typename T>
class vector {
int size_arr;
T * vec = new T;
public:
vector(/*int _size*/) {
vec = new T[0];
size_arr = 0;
};
~vector() {
size_arr = 0;
delete[] vec;
};
vector(vector &v) {
vec = new T[v.size()];
memcpy(vec, v,v.size());
size_arr = v.size();
}
void push_back(T data) {
T *temp = new T[size_arr + 1];
for (int i = 0; i < size_arr; i++)
temp[i] = vec[i];
temp[size_arr] = data;
size_arr++;
delete[] vec;
vec = temp;
};
void push_front(T data){
int j;
T *temp = new T[size_arr + 1];
for ( j = size_arr; j >= 0;j--) {
temp[j + 1] = vec[j];
}
temp[0] = data;
delete[] vec;
vec = temp;
size_arr++;
};
void insert(int index, T data) {
int j;
T *temp = new T[size_arr + 1];
for (int i = 0; i < size_arr ;i++)
temp[i] = vec[i];
for (int i = 0; i < size_arr;i++) {
if (i == index) {
for ( j = size_arr; j >=i;j--) {
temp[j+1] = vec[j];
}
temp[j + 1] = data;
delete[] vec;
vec = temp;
size_arr++;
}
}
};
void pop() {
T *temp = new T[size_arr - 1];
for (int i = 0; i < size_arr-1;i++)
temp[i] = vec[i];
size_arr--;
delete[] vec;
vec = temp;
};
void Delete(int index)
{
T *temp = new T[size_arr - 1];
for (int i = 0; i < index;i++)
temp[i] = vec[i];
for (int i = 0; i < size_arr;i++) {
if (i == index) {
for (int j = i; j < size_arr-1;j++) {
temp[j] = vec[j + 1];
}
size_arr--;
delete[] vec;
vec = temp;
}
}
};
int search(T data) {
for (int i = 0; i < size_arr;i++) {
if (vec[i] == data) {
return i;
}
}
return -1;
};
int size() { return size_arr; };
};
int main() {
vector <int>test;
test.push_front(2);
test.push_front(3);
test.push_back(0);
test.push_back(-1);
test.insert(2, 2);
test.pop();
vector <int > test1;
test1 = test;// problem
test1.pop();
}
The problem is the line test1 = test;// problem, which does not call the copy constructor, but the assignment operator. You did not declare this operator, so the compiler will use the default implementation, which simply copies all member. So, after the assignment test1.vec and test.vec point to the same memory location.
When you change the line (and the one above it) to vector <int > test1{test};, it will call your copy constructor.
You also forgot to #include <cstring> for memcpy, which you should not use for non-POD types.
You have to multiply the size in memcpy with sizeof(T), because memcpy works on bytes, not on types. You also have to use v.vec instead of v.
Here is the fixed version: https://ideone.com/JMn7ww
I think the problem is in your copy operator. You use memcpy() which is a c function. Which should in itself not be a problem (apart from it being not so nice in many opinions). But since memcpy() is a c function, it doesn't know about types, and it takes its size arguments as a count of bytes.
the element you put in is int which is probably 4 bytes. So when your copy contstructor gets called, and the original has 3 elements, there will be 12 bytes in your array, but malloc will only copy 3 of them.
The comments of other people about not properly copying template types are right, so if you make a vector of strings, you cannot just memcpy them, and assume the result will be new strings. For this answer i was assuming you using only basic types as your template arguments like int, or double.

Destructor immediately calls and deletes my arrays

I am working on a Matrix class for a CS project, and I'm trying to work on the constructors. The project calls for two different constructors, one just calling out the numbers of rows and columns and making them all 0 and another using an initializer list to assign the values. The header file so far is:
typedef unsigned int uint;
typedef std::initializer_list<std::initializer_list<double>> i_list;
class Matrix {
public:
double ** arr;
uint mainRows;
uint mainCols;
Matrix(uint rows, uint cols);
Matrix(const i_list & list);
Matrix(const Matrix & m);
~Matrix();
};
Some of the test cases require you to both define the rows and use the initializer list, for example:
Matrix d(2,2);
d = {{1,2},{3,4}};
But I noticed that every time I try and run this kind of code, the destructor will immediately delete the double ** arr which is where the values for the Matrix's are stored. Here is the code for the constructors:
Matrix::Matrix(uint rows, uint cols)
{
mainRows = rows;
mainCols = cols;
arr = new double*[rows];
for (int i = 0; i < mainRows; i++) {
arr[i] = new double[cols];
}
for (int i = 0; i < mainRows; i++) {
for (int j = 0; j < mainCols; j++) {
arr[i][j] = 0;
}
}
}
Matrix::Matrix(const i_list & list)
{
int i = 0, j = 0;
mainRows = list.size();
mainCols = (*list.begin()).size();
arr = new double*[mainRows];
for (std::initializer_list<double> I : list) {
j = 0;
arr[i] = new double[mainCols];
for (double d : I) {
arr[i][j] = d;
j++;
}
i++;
}
}
Matrix::Matrix(const Matrix & m)
{
this->arr = m.arr;
this->mainRows = m.mainRows;
this->mainCols = m.mainCols;
for (uint i = 0; i < mainRows; i++) {
for (uint j = 0; j < mainCols; j++) {
this->arr[i][j] = m.arr[i][j];
}
}
}
Matrix::~Matrix()
{
for (uint i = 0; i < mainRows; i++) {
delete[] arr[i];
}
delete[] arr;
}
I guess since its calling a constructor for the same object twice it's creating two double ** ars and that's why the Destructor want's to delete the original, but then I can't call on the values for other functions. Can somebody help me out with what I'm doing wrong?
The problem is that your copy-constructor only copies the pointer of the source object, not allocates new memory.
This is problematic because
d = {{1,2},{3,4}};
creates a temporary object out of {{1,2},{3,4}}. You statement is actually equal to
d = Matrix({{1,2},{3,4}});
which is equal to
d.operator=(Matrix({{1,2},{3,4}}));
After the assignment is made, you have two objects pointing to the same memory for arr. And then the temporary object is destructed, leading to arr inside d to become invalid, as it no longer points to allocated memory.
The naive solution is simple: Allocate memory for arr to point to in the copy-constructor. The better solution is to stop using pointers and dynamic allocation, and instead use std::vector, and live by the rule of zero, where you don't need any copy-constructor, no copy-assignment operator and no destructor.
This is wrong:
Matrix::Matrix(const Matrix & m)
{
this->arr = m.arr;
this->mainRows = m.mainRows;
this->mainCols = m.mainCols;
for (uint i = 0; i < mainRows; i++) {
for (uint j = 0; j < mainCols; j++) {
this->arr[i][j] = m.arr[i][j];
}
}
}
Note yuo do not creating actual copy here. this->arr = m.arr; makes both pointers to pointing same part of memory so new and old instance of Matrix are sharing this memory. So flowing for loops does nothing.
Than when one of instances is destroyed the other instance is pointing to memory which is freed.

C++ 4d array memory deallocation is slow

My code has a 4D matrix in it for some math problem solving
int**** Sads = new int***[inputImage->HeightLines];
for (size_t i = 0; i < inputImage->HeightLines; i++)
{
Sads[i] = new int**[inputImage->WidthColumns];
for (size_t j = 0; j < inputImage->WidthColumns; j++)
{
Sads[i][j] = new int*[W_SIZE];
for (size_t k = 0; k < W_SIZE; k++)
{
Sads[i][j][k] = new int[W_SIZE];
}
}
}
//do something with Sads...
for (int i = 0; i < inputImage->HeightLines; i++)
{
int*** tempI = Sads[i];
for (int j = 0; j < inputImage->WidthColumns; j++)
{
int** tempJ = tempI[j];
for (int k = 0; k < W_SIZE; k++)
{
delete[] tempJ[k];
}
delete[] Sads[i][j];
}
delete[] Sads[i];
}
delete[] Sads;
The sizes are very large WidthColumns = 2018, HeightLines = 1332, W_SIZE =7, the memory allocation is very fast but the memory deallocation (delete) is very slow.
Is there a way to optimize it?
I tired openMP but it throws unrelated errors of missing DLL which are there... if I removed the #pragma omp parallel for everything works fine. but slow...
Using a pointer to a pointer to... is a bad idea because it will fragment your data a lot.
I would create a class ta manage the indices transform and use 1D array, it's a bit more complicated but it will be faster.
Anyway, a trick: nothing prevent you to build your int**** with pointers to a zone in memory that isn't sparse (1D array you preallocated) and then use it as a 4D array.
I'd probably be inclined to use a std::vector. Now memory allocation is taken care of for me (in one allocation/deallocation) and I get free copy/move semantics.
All I have to do is provide the offset calculations:
#include <vector>
#include <cstddef>
struct vector4
{
vector4(std::size_t lines, std::size_t columns)
: lines_(lines), columns_(columns)
, storage_(totalSize())
{}
auto totalSize() const -> std::size_t
{
return lines_ * columns_ * w_size * w_size;
}
int* at(std::size_t a)
{
return storage_.data() + (a * columns_ * w_size * w_size);
}
int* at(std::size_t a, std::size_t b)
{
return at(a) + (b * w_size * w_size);
}
int* at(std::size_t a, std::size_t b, std::size_t c)
{
return at(a, b) + (c * w_size);
}
int& at(std::size_t a, std::size_t b, std::size_t c, std::size_t d)
{
return *(at(a, b, c) + d);
}
private:
std::size_t lines_, columns_;
static constexpr std::size_t w_size = 32; // ?
std::vector<int> storage_;
};
int main()
{
auto v = vector4(20, 20);
v.at(3, 2, 5, 1) = 6;
// other things
// now let it go out of scope
}
The correct way to create, use, and delete a 4D array is this, using the closure of the statement group to delete the automatic variables.
{
const int H = 10;
const int I = 10;
const int J = 10;
const int K = 10;
int h = 0;
int i = 0;
int j = 0;
int k = 0;
int fourDimArray [H][I][J][K];
fourDimArray[h][i][j][k] = 0;
}
If you have a need to dynamically allocate, then use either STL's list or vector class or use something like this with perhaps inline methods to calculate the index of the 1D array from the 4D array indices if you need blazing speed.
int * fourDimArrayAsOneDim = new int[H*I*J*K];
fourDimArrayAsOneDim[indexFromIndices(h, i, j, k)] = 0;
delete [] fourDimArrayAsOneDim;

copy constructor error: the object has type qualifiers that are not compatible with the member function

im working with simple 2D array,but in my copy constructor i encounter a problem.
Here's a excerpt from my code:
//default constructor
Matrix::Matrix(int r, int c)
{
rows = r;
cols = c;
mainArray = new int[rows*cols];
array = new int *[rows];
for (int i = 0; i < rows; i++)
array[i] = mainArray + (i*cols);
}
//at member
int& Matrix::at(int i, int j)
{
return array[i][j];
}
//copy constructor
Matrix::Matrix(const Matrix & obj)
{
rows = obj.rows;
cols = obj.cols;
mainArray = new int[rows*cols];
array = new int *[rows];
for (int i = 0; i < rows; i++)
array[i] = mainArray + (i*cols);
}
for (int i = 0; i < obj.rows; i++)
{
for (int j = 0; j < obj.cols; j++)
at(i, j) =obj.at(i,j);//PROBLEM
}
}
when im trying to assign at(i,j)=obj.at(i,j) i get this:
the object has type qualifiers that are not compatible with the member function
as far as i know, copy constructor is supposed to be passed by (const class& obj).
what should i do?
That's because your copy constructor take a const parameter, and your method Matrix::at is not const.
I suggest you to do two versions of your at method, one const and one not :
// Use for assignement
int& Matrix::at(int i, int j)
{
return array[i][j];
}
// Use for reading
int Matrix::at(int i, int j) const
{
return array[i][j];
}
Your compiler should know in which case call which one without your help, depending if you are trying to modify or just read your instance :
Matrix matrix(4, 4);
matrix.at(1, 2) = 42; // Assignement method called
int i = matrix.at(1, 2); // Read method called
Realize two versions of at function, one const and one non-const.
int& Matrix::at(int i, int j)
{
return array[i][j];
}
int Matrix::at(int i, int j) const
{
return array[i][j];
}