You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++实现PLU分解时P矩阵异常与析构double free报错排查

问题根因

两个异常(P矩阵输出乱码、double free报错)来自同一个根源:Matrix类未遵守C++资源管理的三/五规则,没有实现拷贝构造函数和拷贝赋值运算符,默认生成的浅拷贝逻辑导致野指针和重复释放。

具体执行流程的问题点:

  • PLU_decomposition方法中创建的P是函数内的局部Matrix对象,函数返回时需要将该局部对象赋值给main函数中定义的外层P变量。由于你没有自定义拷贝赋值逻辑,编译器自动生成的默认赋值操作只会直接复制data指针的值,不会重新分配堆内存、也不会复制数组里的元素内容。
  • 函数执行结束后,局部P对象立刻出作用域触发析构,其data指针指向的所有堆内存被释放。此时main函数中外层P的data指针仍然指向这块已经被回收的内存,属于野指针:调用print_data读取这块内存时,拿到的是内存回收后残留的随机值,就是你看到的那些4.68746e-310之类的无意义极小值。
  • 等main函数执行到末尾,外层P对象触发析构时,会再次对已经释放过的内存地址执行delete[]操作,就会抛出free(): double free detected in tcache 2错误,直接中止程序。

你观察到L、U矩阵结果正确,是因为这两个对象是通过引用传入函数、直接在原对象上修改的,全程没有触发对象拷贝/赋值流程,所以没踩到这个浅拷贝的坑。

修复方案

给Matrix类补全深拷贝逻辑的拷贝构造函数和拷贝赋值运算符即可,参考实现如下:

// 拷贝构造函数
Matrix::Matrix(const Matrix& other) {
    size = other.size;
    data = new double*[size];
    for (int i = 0; i < size; i++) {
        data[i] = new double[size];
        for (int j = 0; j < size; j++) {
            data[i][j] = other.data[i][j];
        }
    }
}

// 拷贝赋值运算符
Matrix& Matrix::operator=(const Matrix& other) {
    if (this == &other) { // 处理自赋值场景
        return *this;
    }
    // 先释放当前对象持有的旧堆内存
    for (int i = 0; i < size; i++) {
        delete[] data[i];
    }
    delete[] data;
    // 按源对象的尺寸开辟新内存,逐元素拷贝内容
    size = other.size;
    data = new double*[size];
    for (int i = 0; i < size; i++) {
        data[i] = new double[size];
        for (int j = 0; j < size; j++) {
            data[i][j] = other.data[i][j];
        }
    }
    return *this;
}

补全上述代码后,对象赋值时会完整复制矩阵的内存内容,不会出现野指针和重复释放问题,排列矩阵P的输出也会恢复正常。
如果使用C++11及以上标准,也可以额外实现移动构造和移动赋值进一步优化性能,但补全上述深拷贝逻辑已经可以彻底解决当前遇到的所有异常。


内容的提问来源于stack exchange,提问作者jerry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 19:15:33