【发布时间】:2016-04-22 18:20:45
【问题描述】:
我正在尝试编写一个实现矩阵和一些基本操作的小库。现在我正在尝试实现 LU 分解。问题是我的程序有时运行没有问题,有时它会提前终止,windows 只是说“test.exe 已达到最高工作状态”。
我正在使用带有以下选项的 g++ 进行编译:
g++ "./Lineair Algebra/Matrix.cpp" "./Lineair Algebra/Determinant.cpp" test.cpp -g -lm -std=c++11 -o test.exe
包含 Determinant.cpp 文件是因为我打算使用分解来计算大小 > 3 的行列式。
调用分解的代码在test.cpp中: 测试.cpp:
#include "./Lineair Algebra/Matrix.hpp"
#include "./Lineair Algebra/Determinant.hpp"
int main (void)
{
Matrix n (4,4);
Matrix& nRef = n;
n.set(0,0,2);
n.set(0,3,1);
n.set(2,0,-2);
n.set(3,0,4);
n.set(1,1,1);
n.set(2,1,-3);
n.set(3,1,-4);
n.set(1,2,3);
n.set(2,2,-5);
n.set(3,2,4);
n.set(0,3,1);
n.set(1,3,-3);
n.set(2,3,2);
n.set(3,3,6);
Matrix tmp1 (4,4);
Matrix tmp2 (4,4);
Matrix& tmp1Ref = tmp1;
Matrix& tmp2Ref = tmp2;
n.print();
cout << "Decomposing" << endl;
n.LUDecompose(tmp1Ref,tmp2Ref);
cout << "Test.cpp regained control" << endl;
n.print();
tmp1.print();
tmp2.print();
cout << "Done printing, returning 0 from test.cpp" << endl;
return 0;
}
Matrix.hpp:
#ifndef MATRIX_HPP
#define MATRIX_HPP
#include <iostream>
#include <vector>
using namespace std;
typedef vector< vector<double> > Table;
class Matrix
{
private:
Table array;
int rows;
int cols;
public:
Matrix();
Matrix(int r, int c);
Matrix(Table t);
~Matrix(void);
//Matrix (double** dp, size_t r, size_t c);
Matrix operator+ (Matrix m);
Matrix operator+ (double d);
Matrix operator- (Matrix m);
Matrix operator- (double d);
Matrix operator* (Matrix m);
Matrix operator* (double d);
void operator*= (double d);
Matrix operator/ (double d);
void operator/= (double d);
bool operator== (Matrix m);
bool operator!= (Matrix m);
bool isSquare () const;
bool isRow () const;
bool isCol () const;
int getElements () const;
int getRows() const;
int getCols() const;
int getSize () const;
double get(int row, int col) const;
void getSubMatrix (int rowFrom, int colFrom, int rowTo, int colTo, Matrix& dest) const;
void getTable (Table& t) const;
int getRow (int row, Matrix& dest) const;
int getCol (int col, Matrix& dest) const;
void set(int row, int col, double value);
void set (Table& t);
void expand (int r, int c);
int addRows (int row, const Matrix& rrm);
int addCols (int col, const Matrix& rcm);
void gaussEliminate (Matrix& lower, Matrix& upper);
int LUDecompose (Matrix& l, Matrix& u);
int transpose (Matrix& dest);
void print ();
};
#endif
Matrix.cpp 大约有 600 行,所以我会尽量只发布必要的:
Matrix.cpp:构造函数和析构函数(仅用于调试)
#include <iostream>
#include <vector>
#include "Matrix.hpp"
using namespace std;
typedef vector< vector<double> > Table;
Matrix::Matrix()
{
array = Table (1, vector <double> (1));
array[0][0] = 0;
}
Matrix::Matrix(int r, int c)
{
array = Table (c, vector <double> (r));
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
this->set(i, j, 0);
}
}
}
Matrix::Matrix(Table t) : array(t) {}
Matrix::~Matrix(void)
{
cout << "Deleting matrix" << endl;
}
Matrix.cpp:LUDecompose 方法
int Matrix::LUDecompose (Matrix& refLower, Matrix& refUpper)
{
if (!this->isSquare())
{
cout << "Given matrix is not a square matrix" << endl;
return -1;
}
else
{
double c = 0;
Matrix rowMatrix (1,this->getCols());
Matrix& refRowMatrix = rowMatrix;
refUpper = *this;
for (int i = 1; i < this->getRows(); i++)
{
for (int j = 0; j < i; j++)
{
if (i >= j)
{
refUpper.getRow(j,refRowMatrix);
rowMatrix *= refUpper.get(i,j);
rowMatrix /= refUpper.get(j,j);
rowMatrix *= -1.0;
c = refUpper.get(i,j) / refUpper.get(j,j);
refUpper.addRows(i,refRowMatrix);
refLower.set(i, j, c);
cout << "Leaving if statement" << endl;
}
cout << "Leaving inner for loop" << endl;
}
cout << "Leaving outer for loop" << endl;
}
for (int i = 0; i < this->getRows(); i++)
{
refLower.set(i,i,1);
}
cout << "Returning 0 from LUDecompose" << endl;
return 0;
}
}
现在我知道有一些库可以为我做这件事,但这并不是重点,我只是想在这里学习。 还要记住,我主要是自学成才,所以我的代码可能不符合(某些人的)专业标准。
当我在 gdb 之外运行此代码时,这是我得到的输出:
Deleting matrix
Deleting matrix
[2 0 0 1 ]
[0 1 3 -3 ]
[-2 -3 -5 2 ]
[4 -4 4 6 ]
Decomposing
Deleting matrix
Leaving if statement
Leaving inner for loop
Leaving outer for loop
Leaving if statement
Leaving inner for loop
Leaving if statement
Leaving inner for loop
Leaving outer for loop
Leaving if statement
Leaving inner for loop
Leaving if statement
Leaving inner for loop
Leaving if statement
Leaving inner for loop
Leaving outer for loop
Returning 0 from LUDecompose
Deleting matrix
Test.cpp regained control
[2 0 0 1 ]
[0 1 3 -3 ]
[-2 -3 -5 2 ]
[4 -4 4 6 ]
[1 0 0 0 ]
[0 1 0 0 ]
[-1 -3 1 0 ]
[2 -4 4 1 ]
[2 0 0 1 ]
[0 1 3 -3 ]
[0 0 4 -6 ]
[0 0 0 16 ]
Done printing, returning 0 from test.cpp
Deleting matrix
Deleting matrix
Deleting matrix
成功运行,或以下运行不成功:
Deleting matrix
Deleting matrix
[2 0 0 1 ]
[0 1 3 -3 ]
[-2 -3 -5 2 ]
[4 -4 4 6 ]
Decomposing
Deleting matrix
Leaving if statement
Leaving inner for loop
Leaving outer for loop
Leaving if statement
Leaving inner for loop
Leaving if statement
Leaving inner for loop
Leaving outer for loop
Leaving if statement
Leaving inner for loop
Leaving if statement
Leaving inner for loop
Leaving if statement
Leaving inner for loop
Leaving outer for loop
Returning 0 from LUDecompose
Deleting matrix
从 GDB 运行代码时,它总是崩溃,GDB 产生以下输出:
[New Thread 1584.0x8b8]
[New Thread 1584.0xdb8]
[New Thread 1584.0x13fc]
[New Thread 1584.0x10b8]
Deleting matrix
Deleting matrix
[2 0 0 1 ]
[0 1 3 -3 ]
[-2 -3 -5 2 ]
[4 -4 4 6 ]
Decomposing
Deleting matrix
Leaving if statement
Leaving inner for loop
Leaving outer for loop
Leaving if statement
Leaving inner for loop
Leaving if statement
Leaving inner for loop
Leaving outer for loop
Leaving if statement
Leaving inner for loop
Leaving if statement
Leaving inner for loop
Leaving if statement
Leaving inner for loop
Leaving outer for loop
Returning 0 from LUDecompose
Deleting matrix
warning: HEAP[test.exe]:
warning: Heap block at 00801188 modified at 00801198 past requested size of 8
Program received signal SIGTRAP, Trace/breakpoint trap.
0x76fdee8b in ?? ()
我已经在网上查找了错误,我怀疑它超出了范围,但我不明白为什么。
请温柔一点,这是我第一次这样的问题;)
编辑:稍微清理一下 test.cpp,删除未使用的行列式和矩阵
编辑 2:我知道我需要调试这个程序。问题是我不明白为什么它会崩溃。当我在 gdb 中使用 bt 时,它会将我指向析构函数,并且上面的任何帧都与向量(de)分配器有关。
编辑 3:删除 =operator,将构造函数中 [] 的使用更改为 at() 方法。根据要求,这里是 set 方法:
void Matrix::set(int row, int col, double value)
{
array[row][col] = value;
}
void Matrix::set (Table& t)
{
if (t.size() > this->getCols())
{
this->expand(0,t.size() - this->getCols());
}
if (t[0].size() > this->getRows())
{
this->expand(t[0].size() - this->getRows(),0);
}
for (int i = 0; i < t[0].size(); i++)
{
for (int j = 0; j < t.size(); j++)
{
this->set(i,j,t[i][j]);
}
}
}
编辑 4:更新构造函数以反映 Paul McKenzie 的评论
编辑 5:我很抱歉没有首先发布以下功能,我只是认为我的帖子已经足够长了...... 不管怎样,你去吧:
void Matrix::operator*= (double d)
{
for (int i = 0; i < this->getRows(); i++)
{
for (int j = 0; j < this->getCols(); j++)
{
this->set(i, j, this->get(i,j) * d);
}
}
}
void Matrix::operator/= (double d)
{
if (d != 0)
{
for (int i = 0; i < this->getRows(); i++)
{
for (int j = 0; j < this->getCols(); j++)
{
this->set(i, j, this->get(i,j) / d);
}
}
}
else
{
cout << "Can not divide by zero" << endl;
}
}
bool Matrix::isSquare () const
{
if (this->getRows() == this->getCols())
{
return true;
}
else
{
return false;
}
}
int Matrix::getRows() const
{
return this->array.at(0).size();
}
int Matrix::getCols() const
{
return this->array.size();
}
double Matrix::get(int row, int col) const
{
if ((row < this->getRows()) && (col < this->getCols()))
{
return array[row][col];
}
else
{
cout << "Couldn't get (" << row << "," << col <<"), element is out of bounds. dim = " << this->getRows() << " x " << this->getCols() << endl;
return -1;
}
}
int Matrix::getRow (int row, Matrix& dest) const
{
if (!dest.isRow())
{
cout << "Destination matrix is not a row matrix" << endl;
return -1;
}
else
{
for (int i = 0; i < this->getCols(); i++)
{
dest.set(0, i, this->get(row,i));
}
return 0;
}
}
int Matrix::addRows (int row, const Matrix& rrm)
{
if (!rrm.isRow())
{
cout << "Specified matrix is not a row matrix." << endl;
return -1;
}
else if (rrm.getCols() != this->getCols())
{
cout << "Matrix dimensions do not match." << endl;
return -1;
}
else if (row >= this->getRows())
{
cout << "Given row number exceeds amount of rows in matrix." << endl;
return -1;
}
else
{
for (int i = 0; i < rrm.getCols(); i++)
{
this->set(row, i, this->get(row, i) + rrm.get(0,i));
}
return 0;
}
}
编辑 6:我通过 VS 的调试器运行我的代码,这给了我一个超出范围的异常 Matrix::set (int row, int col, double value)。奇怪的是,我已经更新了进行范围检查的方法。调用堆栈如下所示:
Matrix.cpp::set(int row, int col, double value) @ line 415 (array.at(row).at(col) = value;)
Matrix.cpp::Matrix(int r, int c) @ line 25(内部for循环的右括号)
Matrix.cpp::LUDecompose(Matrix& refLower, Matrix& refUpper) @ line 526 (Matrix rowMatrix(1, this->getCols());)
Test.cpp::Main @ line 35 (cout << "Test.cpp regained control" << endl;)
这是该方法当前的样子:
void Matrix::set(int row, int col, double value)
{
if ((row < this->getRows()) && (col < this->getCols()))
{
array.at(row).at(col) = value;
}
else
{
cout << "Trying to assign to (" << row << "," << col << "): Out of bounds, dim = " << this->getRows() << " x " << this->getCols() << endl;
}
}
编辑 7: 在 VS 中摆弄了一下之后,我能够修复代码。我进行了多次编辑,但我很确定导致上述异常的原因是 array.at(n) 返回第 n 列(而不是第 n 行,如我的代码所示) 和 array.at(n).at(m) 返回位置 (m,n) 处的元素(其中 m 是第 m 行,n 是第 n 列) 感谢大家帮助我,这里是固定set方法的一个副本:
void Matrix::set(int row, int col, double value)
{
if ((row < this->getRows()) && (col < this->getCols()))
{
array.at(col).at(row) = value;
}
else
{
cout << "Trying to assign to (" << row << "," << col << "): Out of bounds, dim = " << this->getRows() << " x " << this->getCols() << endl;
}
}
【问题讨论】:
-
TL;博士。你需要调试你的程序。
-
确保使用调试符号进行编译(
-g标志为g++)并在 GDB 中尝试bt以查看代码崩溃的位置。这也比在整个代码中打印到控制台进行调试要容易一些。 -
为什么你的
Matrix类有一个赋值运算符(operator=)?不需要它,因为您的 Matrix 类不使用指针或它需要管理的任何资源。摆脱它。编译器的默认版本非常好并且可以工作。您的版本——我们不知道它是做什么的,它是否有效,是否存在错误等。您需要展示您的实现,然后可以确定这是否是导致此类问题的原因。如果这是一个问题 - 再次 - 删除它。 -
我删除了 = 运算符,但不幸的是,这并没有解决我的问题。无论如何,谢谢你帮助我。我什至不知道 g++ 会生成默认运算符...所以,如果我理解正确,您需要重载这些运算符的唯一时间是您必须手动管理资源(new、delete、malloc()、free( ), 指针, ...)
-
默认情况下,每个 C++ 类都有一个复制构造函数和赋值运算符。不是
g++,这是 C++ 语言的规则。至于你的问题,是的,如果你要引入指针和动态内存管理,你应该有这些函数的用户定义版本。