c++ - 释放指针时出现段错误

标签 c++ segmentation-fault c++17 double-free

class matrix
{
public:
    int nrow;
    int ncol;
    double **m;

    matrix(int r, int c)
    {
        nrow = r; ncol = c;

        m = (double**)malloc(nrow*sizeof(double*));
        for(int i=0; i<nrow; i++)
            m[i] = (double*)malloc(ncol*sizeof(double));

        for(int i=0; i<nrow; i++)
            for(int j=0; j<ncol; j++)
                m[i][j] = 0;
    }

    ~matrix()
    {
        for(int i=0; i<nrow; i++)
        {
            printf("destructor loop: %d\n", i); fflush(stdout);
            free(m[i]);
        }
        free(m);
    }

    matrix(const matrix& that)
    {
        this->nrow = that.nrow;
        this->ncol = that.ncol;

        this->m = (double**)malloc(nrow*sizeof(double*));   // dynamic mem allocation
        for(int i=0; i<this->nrow; i++)
            m[i] = (double*)malloc(ncol*sizeof(double));

        for(int i=0; i<that.nrow; i++)
            for(int j=0; j<that.ncol; j++)
                this->m[i][j] = that.m[i][j]; 
    }

    void operator=(const matrix &that)
    {
        this->nrow = that.nrow;
        this->ncol = that.ncol;

        for(int i=0; i<nrow; i++)  // clear current m
            free(m[i]);
        free(m);

        this->m = (double**)malloc(nrow*sizeof(double*));   // dynamic mem allocation
        for(int i=0; i<this->nrow; i++)
            m[i] = (double*)malloc(ncol*sizeof(double));

        for(int i=0; i<that.nrow; i++)
            for(int j=0; j<that.ncol; j++)
                this->m[i][j] = that.m[i][j]; 
    }

    void show()
    {
        printf("  Marix:\n");
        for(int i=0; i<nrow; i++)
        {
            printf("  ");
            for(int j=0; j<ncol; j++)
            {
                if(m[i][j] >= 0) printf(" ");
                printf("%.6lf ", m[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }

    matrix cofactor(int r, int c) // returns cofactor of a[r][c]
    {
        printf("cofactor: size:(%d, %d) element:(%d, %d)\n", nrow, ncol, r, c); fflush(stdout);

        matrix ans(nrow-1, ncol-1);

        int x = 0, y = 0;
        for(int i=0; i<nrow; i++)
        {
            if(i == r) continue;
            for(int j=0; j<ncol; j++)
            {
                if(j == c) continue;
                ans.m[x][y] = m[i][j];
                y++;
            }
            x++;
        }
        return ans;
    }

    double det()
    {
        if(nrow != ncol)
        {
            printf("non-square matrix: (%d, %d)\n\n", nrow, ncol);
            exit(1);
        }

        if(nrow == 1) return m[0][0]; 
        if(nrow == 2) 
        {
            double ans = m[0][0]*m[1][1] - m[1][0]*m[0][1];
            return ans;
        }

        double ans = 0;
        int sign = 1;
        for(int i=0; i<nrow; i++)
        {
            printf("det[size:%d, %d] loop row: %d\n", nrow, ncol, i); fflush(stdout);
            matrix a(2, 2); 
            a = cofactor(i, 0);
            ans += (sign*a.det());
            sign = sign*(-1);
        }
        return ans;
    }
};

int main()
{
    matrix c(3, 3);
    c.m[0][0] = 2; c.m[0][1] = -3; c.m[0][2] =  1;
    c.m[1][0] = 2; c.m[1][1] =  0; c.m[1][2] = -3;
    c.m[2][0] = 1; c.m[2][1] =  4; c.m[2][2] =  5;

    c.show();
    printf("determinant: %lf\n", c.det());

    return 0;
}

为偶数 3x3 矩阵调用 det 函数时会发生段错误。
我没有使用复杂调试器的经验,但使用 printf 语句看起来运行时错误发生在析构函数中的循环迭代期间。我也尝试过使用 vector < vector <双>>而不是双**。我认为在这种情况下它不需要析构函数。然后它给了我一个“双重免费错误”。我了解它何时发生,但在我的代码中找不到错误。我也尝试过计算内联辅因子而不是调用函数,但它没有帮助。

最佳答案

    int x = 0, y = 0;
    for(int i=0; i<nrow; i++)
    {
        if(i == r) continue;
        for(int j=0; j<ncol; j++)
        {
            if(j == c) continue;
            ans.m[x][y] = m[i][j];
            y++;
        }
        x++;
    }
递增逻辑 y在这里坏了。做一个简单的心理实验。如果原始矩阵是 3x3,并且它们在这里被缩减为 2x2矩阵,你的ans ,那么您期望 ans 中的每个值在这里初始化,并且
            ans.m[x][y] = m[i][j];
            y++;
将被执行四次。由于y初始设置为 0 并且永远不会重置为 0 y 的值此分配中使用的范围为 0 到 3,因此,在某些时候,这将尝试将某些内容分配给 ans.m[x][3] ,这当然不存在,随之而来的是山寨现象。
似乎这里明显的意图是重置
  y=0;
作为外部for的第一笔交易循环,而不是一开始就循环一次。

关于c++ - 释放指针时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63311040/

相关文章:

c++ - 我可以在 C++ 中通过 > < 比较字符串吗

c++ - 返回make_shared <Base>,继承和强制转换为Derived无法按预期工作吗?

c++ - 与任何类型的函数的接口(interface)

c++出现奇怪的段错误

c - 如何让 Check 生成核心转储?

c - 在链表中获取段错误

c++ - MacOS c++17 : call to abs ambiguous 上的 cmath 错误

c++ - 绘制点或填充圆

c++ - 已经到达终点的双向迭代器是否应该在 C++ 中保持递减?

C++ 重写继承的静态 const 变量的值