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
相关产品推荐
相关产品推荐

