三行代码  ›  专栏  ›  技术社区  ›  CH_YUR

为什么这段代码有分段错误?

  •  0
  • CH_YUR  · 技术社区  · 1 月前

    这是我关于Matrix的代码(我决定练习OOP编写自己的Matrix类)

    矩阵水电站

    #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
    

    矩阵cpp

    #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;
    }
    

    主要的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;
    }
    

    当我打开程序时,在添加两个矩阵后,它会给我一个分段错误。在这种情况下,对我来说更有趣的是 Matrix.cpp, Matrix Matrix::operation+... .

    当我删除这两行时(检查等式2矩阵),当我打开程序时,它不会给我一个分段错误,但当我添加这两行时,程序会给我一个s.f.你能告诉我为什么它会这样工作吗?

    1 回复  |  直到 1 月前
        1
  •  2
  •   Remy Lebeau    1 月前

    double[x*y] 数组而不是二维数组 double*[x] 属于 double[y] 数组。这将使内存管理更容易一些,因为您只需要处理一个数组,而不是多个数组。

    无论如何,你的 Matrix(const Matrix &) 复制构造函数不应为空 delete[] “有什么事吗 mtrx 然而,因为 mtrx 尚未初始化(它指向随机内存)。该构造函数的其余部分也没有正确分配数组。您可以在中正确分配数组 Matrix(u_int, u_int) 构造函数,所以只需将该逻辑复制到复制构造函数中。然后完成复制构造函数,你知道,通过实际复制 double 来自 Matrix 被抄袭。

    至于 operator+ ,如果你不知道该怎么做 return 对于不同大小的矩阵,我建议 throw “这是一个例外。

    此外,即使您当前的代码还没有使用它,您也应该添加一个副本分配 operator= 结束 Rule of 3 (您已经有了复制构造函数和析构函数)。

    试试这个:

    #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 &);
    
        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"
    #include <utility>
    #include <stdexcept>
    
    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)
    {
        if (&a != this)
        {
            Matrix tmp(a);
            std::swap(mtrx, tmp.mtrx);
        }
        return *this;
    }
    
    Matrix Matrix::operator+(const Matrix &a) const
    {
        if (!IsEqualSize(a))
            throw std::logic_error("Cannot add matrices of different sizes");
    
        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;
    }