Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why it is a segmentation fault with this code fragment?

Here is my code about Matrix (I decided to practise OOP writing own Matrix class)

Matrix.hpp

#ifndef MATRIX_HEADER
#define MATRIX_HEADER

typedef unsigned int u_int;

class Matrix
{
    double **mtrx;
    u_int x, y;

public:
    Matrix(u_int a, u_int b);
    Matrix(const Matrix &);
    ~Matrix();

    double det();

    Matrix operator+(const Matrix &) const;
    Matrix operator-(const Matrix &) const;                           
    Matrix operator*(const Matrix &) const;
    friend Matrix operator*(const Matrix &, const double &);
    Matrix operator/(const Matrix &) const;
    double *operator[](const u_int idx) const { return mtrx[idx]; }

    bool IsEqual(const Matrix &) const;
    u_int GetX() const { return x; }
    u_int GetY() const { return y; }
};

#endif

Matrix.cpp

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#include "Matrix.hpp"

Matrix::Matrix(u_int a, u_int b) : x(a), y(b)
{
    mtrx = new double *[x];
    for (u_int i = 0; i < x; i++)
        mtrx[i] = new double[y];
}

Matrix::Matrix(const Matrix &ref)
{
    if (mtrx)
    {
        for (u_int i = 0; i < x; i++)
            delete[] mtrx[i];
        delete[] mtrx;
    }
    x = ref.x;
    y = ref.y;
    *mtrx = new double[x];
    for (u_int i = 0; i < x; i++)
        mtrx[i] = new double[y];
}

Matrix::~Matrix()
{
    if (mtrx)
    {
        for (u_int i = 0; i < x; i++)
            delete[] mtrx[i];
        delete[] mtrx;
    }
}

bool Matrix::IsEqual(const Matrix &a) const     // If sizes of matrixes are equal
{                                               // matrixes are equal
    return (a.GetX() == x) && (a.GetY() == y);
}

Matrix Matrix::operator+(const Matrix &a) const
{
    if (!IsEqual(a))                            // Check on equality matrixes
        return Matrix(1,1);                     // I have not any idea yet what          
    Matrix matrix(x, y);                        // should it give is sizes 
    for (u_int i = 0; i < x; i++)               // of Matrix are not equal
        for (u_int j = 0; j < y; j++)
            matrix[i][j] = a.mtrx[i][j] + mtrx[i][j];
    return matrix;
}

main.cpp

#include <stdio.h>
#include "Matrix.hpp"

int main()
{
    Matrix a(2, 5);
    Matrix b(2, 5);
    for (u_int i = 0; i < a.GetX(); i++)
    {
        for (u_int j = 0; j < a.GetY(); j++)
        {
            a[i][j] = i + j;
        }
    }
    for (u_int i = 0; i < b.GetX(); i++)
    {
        for (u_int j = 0; j < b.GetY(); j++)
        {
            b[i][j] = i + j;
        }
    }
    Matrix c = a + b;
    return 0;
}

When I turn on my program, it throws me a segmentation fault after adding two matrixes. The more interesting thing for me in that situation is first 2 lines in Matrix.cpp, Matrix Matrix::operation+....

When I delete these 2 lines (check on equality 2 matrixes), when I turn on my program, it doesn’t throw me a segmentation fault, but when I add these 2 lines, the program throws me a s.f. Can you tell me why does it work like that?

>Solution :

You might consider using a 1D double[x*y] array instead of a 2D double*[x] of double[y] arrays. It will make memory management a bit easier, since you will have only 1 array to deal with, instead of multiple arrays.

In any case, your Matrix(const Matrix &) copy constructor should not be delete[]‘ing anything, because nothing has been initialized yet. And the rest of that constructor is not allocating the arrays correctly. You allocate them correctly in the Matrix(u_int, u_int) constructor, so copy that logic into the copy constructor. And then finish off the copy constructor by, you know, actually copying values from the input Matrix.

As for operator+, if you don’t know what you should return for different sized matrices, then I would suggest throw‘ing an exception instead.

You are also missing an operator= to finish off the Rule of 3/5/0.

Try this:

#ifndef MATRIX_HEADER
#define MATRIX_HEADER

typedef unsigned int u_int;

class Matrix
{
    double **mtrx;
    //or: double *mtrx;
    u_int x, y;

public:
    Matrix(u_int a, u_int b);
    Matrix(const Matrix &);
    ~Matrix();

    double det();

    Matrix operator+(const Matrix &) const;
    Matrix operator-(const Matrix &) const;                           
    Matrix operator*(const Matrix &) const;
    friend Matrix operator*(const Matrix &, const double &);
    Matrix operator/(const Matrix &) const;
    double* operator[](const u_int idx) const {
        return mtrx[idx];
        //or: return &mtrx[idx*x];
    }

    bool IsEqualSize(const Matrix &) const;
    u_int GetX() const { return x; }
    u_int GetY() const { return y; }
};

#endif
#include "Matrix.hpp"

Matrix::Matrix(u_int a, u_int b)
    : x(a), y(b)
{
    mtrx = new double*[x];
    for (u_int i = 0; i < x; ++i) {
        mtrx[i] = new double[y];
    }

    // or: mtrx = new double[x*y];
}

Matrix::Matrix(const Matrix &ref)
    : x(ref.x), y(ref.y)
{
    mtrx = new double*[x];
    for (u_int i = 0; i < x; ++i) {
        mtrx[i] = new double[y];
        for (u_int j = 0; j < y; ++j) {
            mtrx[i][j] = ref.mtrx[i][j];
        }
    }

    /* or:
    u_int size = x*y;
    mtrx = new double[size];
    for (u_int i = 0; i < size; ++i) {
        mtrx[i] = ref.mtrx[i];
    }
    */
}

Matrix::~Matrix()
{
    // this loop is not needed for a 1D array...
    for (u_int i = 0; i < x; ++i) {
        delete[] mtrx[i];
    }

    delete[] mtrx;
}

bool Matrix::IsEqualSize(const Matrix &a) const
{
    return (a.GetX() == x) && (a.GetY() == y);
}

Matrix Matrix::operator+(const Matrix &a) const
{
    if (!IsEqualSize(a))
        throw ...;

    Matrix matrix(x, y);

    for (u_int i = 0; i < x; ++i) {
        for (u_int j = 0; j < y; ++j)
            matrix.mtrx[i][j] = mtrx[i][j] + a.mtrx[i][j];
    }

    /* or:
    u_int size = x*y;
    for (u_int i = 0; i < size; ++i) {
        matrix.mtrx[i] = mtrx[i] + a.mtrx[i];
    }
    */

    return matrix;
}

...
#include <stdio.h>
#include "Matrix.hpp"

int main()
{
    Matrix a(2, 5);
    Matrix b(2, 5);

    for (u_int i = 0; i < a.GetX(); ++i)
    {
        for (u_int j = 0; j < a.GetY(); ++j)
        {
            a[i][j] = i + j;
        }
    }

    for (u_int i = 0; i < b.GetX(); ++i)
    {
        for (u_int j = 0; j < b.GetY(); ++j)
        {
            b[i][j] = i + j;
        }
    }

    Matrix c = a + b;

    return 0;
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading