MAtrix 乘法中的分段错误
Segmentation Fault in MAtrix Multiplication
我几乎是C/C++的初学者。我试图实现一个程序来使用矩阵幂返回第 n 个斐波那契数的值。我编写了以下代码:
#include <cmath>
#include <iostream>
using namespace std;
typedef struct Matrix {
unsigned long long a_00;
unsigned long long a_01;
unsigned long long a_10;
unsigned long long a_11;
}Matrix;
Matrix* init_matrix(unsigned long long n);
Matrix* init_matrix(unsigned long long a_00, unsigned long long a_01,
unsigned long long a_10, unsigned long long a_11);
Matrix* mult_matrix(Matrix* A, Matrix* B);
Matrix* expo_matrix(Matrix* A,unsigned int n);
unsigned long long fib_matrix_expo(unsigned int n);
int main() {
unsigned int n;
cin >> n;
unsigned long long result = fib_matrix_expo(n);
cout << result << endl;
return 0;
}
Matrix* init_matrix(unsigned long long n) {
Matrix* ret_matrix = (Matrix*)::operator new (sizeof(Matrix));
(ret_matrix->a_00) = n;
(ret_matrix->a_01) = n;
(ret_matrix->a_10) = n;
(ret_matrix->a_11) = n;
return ret_matrix;
}
Matrix* init_matrix(unsigned long long a_00, unsigned long long a_01,
unsigned long long a_10, unsigned long long a_11) {
/*==================================================================================*/
Matrix* ret_matrix = (Matrix*)::operator new (sizeof(Matrix));
(ret_matrix->a_00) = a_00;
(ret_matrix->a_01) = a_01;
(ret_matrix->a_10) = a_10;
(ret_matrix->a_11) = a_11;
return ret_matrix;
}
Matrix* matrix_mult(Matrix* A, Matrix* B) {
Matrix* result = (Matrix*)::operator new (sizeof(Matrix));
(result->a_00) = ((A->a_00) * (B->a_00) + (A->a_01)*(B->a_10));
(result->a_01) = ((A->a_00) * (B->a_01) + (A->a_01)*(B->a_11));
(result->a_10) = ((A->a_10) * (B->a_00) + (A->a_11)*(B->a_10));
(result->a_11) = ((A->a_10) * (B->a_01) + (A->a_11)*(B->a_11));
return result;
}
Matrix* matrix_expo(Matrix* base_matrix, unsigned int index) {
Matrix* result;
if (index == 0) {
result = init_matrix(1);
}
else if (index == 1) {
result = base_matrix;
}
else {
Matrix* temp = matrix_expo(base_matrix,static_cast<unsigned int>(index/2));
result = matrix_mult( matrix_expo(temp,2), matrix_expo(base_matrix,(index % 2)) );
}
return result;
}
unsigned long long fib_matrix_expo(unsigned int n) {
unsigned long long result = 0;
Matrix* base = init_matrix(1,1,1,0);
if (n == 0) {
result = 0;
}
else {
base = matrix_expo(base,(n-1));
result = (base->a_00);
}
return result;
}
但是此代码会导致值>= 3 的分段错误。我觉得问题出在 mult_matrix(( 函数上,但我找不到它。请帮忙。
编辑:已找到导致溢出的错误,但此处似乎还存在其他逻辑错误。特别是编辑后的代码输出错误的值,并且输出到连续输入(如 1 和 2、3 和 4、5 和 6(是相同的。:(
编辑后的代码:
#include <cmath>
#include <iostream>
using namespace std;
typedef struct Matrix {
unsigned long long a_00;
unsigned long long a_01;
unsigned long long a_10;
unsigned long long a_11;
}Matrix;
Matrix* init_matrix(unsigned long long n);
Matrix* init_matrix(unsigned long long a_00, unsigned long long a_01,
unsigned long long a_10, unsigned long long a_11);
Matrix* mult_matrix(Matrix* A, Matrix* B);
Matrix* expo_matrix(Matrix* A,unsigned int n);
unsigned long long fib_matrix_expo(unsigned int n);
int main() {
unsigned int n;
cin >> n;
unsigned long long result = fib_matrix_expo(n);
cout << result << endl;
return 0;
}
Matrix* init_matrix(unsigned long long n) {
Matrix* ret_matrix = (Matrix*)::operator new (sizeof(Matrix));
(ret_matrix->a_00) = n;
(ret_matrix->a_01) = n;
(ret_matrix->a_10) = n;
(ret_matrix->a_11) = n;
return ret_matrix;
}
Matrix* init_matrix(unsigned long long a_00, unsigned long long a_01,
unsigned long long a_10, unsigned long long a_11) {
/*==================================================================================*/
Matrix* ret_matrix = (Matrix*)::operator new (sizeof(Matrix));
(ret_matrix->a_00) = a_00;
(ret_matrix->a_01) = a_01;
(ret_matrix->a_10) = a_10;
(ret_matrix->a_11) = a_11;
return ret_matrix;
}
Matrix* matrix_mult(Matrix* A, Matrix* B) {
Matrix* result = (Matrix*)::operator new (sizeof(Matrix));
(result->a_00) = ((A->a_00) * (B->a_00) + (A->a_01)*(B->a_10));
(result->a_01) = ((A->a_00) * (B->a_01) + (A->a_01)*(B->a_11));
(result->a_10) = ((A->a_10) * (B->a_00) + (A->a_11)*(B->a_10));
(result->a_11) = ((A->a_10) * (B->a_01) + (A->a_11)*(B->a_11));
return result;
}
Matrix* matrix_expo(Matrix* base_matrix, unsigned int index) {
Matrix* result;
if (index == 0) {
result = init_matrix(1);
}
else if (index == 1) {
result = base_matrix;
}
else {
Matrix* temp = matrix_expo(base_matrix,static_cast<unsigned int>(index/2));
result = matrix_mult(temp,temp);
result = matrix_mult(result,matrix_expo(base_matrix,(index % 2)));
}
return result;
}
unsigned long long fib_matrix_expo(unsigned int n) {
unsigned long long result = 0;
Matrix* base = init_matrix(1,1,1,0);
if (n == 0) {
result = 0;
}
else {
base = matrix_expo(base,(n-1));
result = (base->a_00);
}
return result;
}
编辑:此错误也已解决。但正如保罗所指出的,这有很多记忆泄漏。我将尝试在不使用手动动态内存分配的情况下实现这一点并重新发布它。然后按照 n.m 的建议。我将在使用构造函数并删除其他不必要的复杂功能后更新代码。当前工作代码:
编辑:没有内存泄漏的代码:
#include <cmath>
#include <iostream>
using namespace std;
struct Matrix {
unsigned long long a_00;
unsigned long long a_01;
unsigned long long a_10;
unsigned long long a_11;
};
Matrix init_matrix(unsigned long long n);
Matrix init_matrix(unsigned long long a_00, unsigned long long a_01,
unsigned long long a_10, unsigned long long a_11);
Matrix mult_matrix(const Matrix& A, const Matrix& B);
Matrix expo_matrix(const Matrix& A,unsigned int n);
unsigned long long fib_matrix_expo(unsigned int n);
int main() {
unsigned int n;
cin >> n;
unsigned long long result = fib_matrix_expo(n);
cout << result << endl;
return 0;
}
Matrix init_matrix(unsigned long long n) {
Matrix ret_matrix;
ret_matrix.a_00 = n;
ret_matrix.a_01 = n;
ret_matrix.a_10 = n;
ret_matrix.a_11 = n;
return ret_matrix;
}
Matrix init_matrix(unsigned long long a_00, unsigned long long a_01,
unsigned long long a_10, unsigned long long a_11) {
/*==================================================================================*/
Matrix ret_matrix;
ret_matrix.a_00 = a_00;
ret_matrix.a_01 = a_01;
ret_matrix.a_10 = a_10;
ret_matrix.a_11 = a_11;
return ret_matrix;
}
Matrix matrix_mult(const Matrix& A, const Matrix& B) {
Matrix result;
result.a_00 = ((A.a_00) * (B.a_00) + (A.a_01)*(B.a_10));
result.a_01 = ((A.a_00) * (B.a_01) + (A.a_01)*(B.a_11));
result.a_10 = ((A.a_10) * (B.a_00) + (A.a_11)*(B.a_10));
result.a_11 = ((A.a_10) * (B.a_01) + (A.a_11)*(B.a_11));
return result;
}
Matrix matrix_expo(const Matrix& base_matrix, unsigned int index) {
Matrix result;
if (index == 0) {
result = init_matrix(1);
}
else if (index == 1) {
result = base_matrix;
}
else {
Matrix temp = matrix_expo(base_matrix,static_cast<unsigned int>(index/2));
result = matrix_mult(temp,temp);
if(index % 2 == 1) {
result = matrix_mult(result,base_matrix);
}
}
return result;
}
unsigned long long fib_matrix_expo(unsigned int n) {
unsigned long long result = 0;
Matrix base = init_matrix(1,1,1,0);
if (n == 0) {
result = 0;
}
else {
base = matrix_expo(base,(n-1));
result = base.a_00;
}
return result;
}
由于这里的递归,您在matrix_expo
函数中存在堆栈溢出
Matrix* temp = matrix_expo(base_matrix,static_cast<unsigned int>(index/2));
result = matrix_mult( matrix_expo(temp,2), matrix_expo(base_matrix,(index % 2)) );
让我们看看为什么
Matrix matrix_expo(Matrix base_matrix, unsigned int index) {
Matrix result;
if (index == 0) {
result = init_matrix(1);
}
else if (index == 1) {
result = base_matrix;
}
else {
Matrix temp = matrix_expo(base_matrix,static_cast<unsigned int>(index/2));
result = matrix_mult( matrix_expo(temp,2), matrix_expo(base_matrix,(index % 2)) );
}
return result;
}
如果index == 2
则始终达到matrix_expo(temp, 2)
,这会导致无限递归。
其他一些问题是new
和从不使用delete
,这里实际上失去了delete
的机会
base = matrix_expo(base,(n-1));
因为可以使用new
分配base
并且您重新确定指向new
分配内存的基本指针。
我说可以使用new
result = base_matrix;
在这里,如果出现前面提到的情况,您将返回base
它自己,但在任何其他情况下,此函数中要result
的其他赋值将使用new
分配,这将返回指向最初分配的内存的指针,因此,如果您使用 delete
运算符释放此内存, 你有机会加倍免费。
这是一个使用类进行Matrix
的C++实现。不幸的是,我对矩阵的了解不足以指出原始代码的"问题"问题;简单地用类重写它似乎已经摆脱了这个问题。我无法解释您的expo
函数内部工作原理,所以我将其编写为一个简单的循环。
使用类意味着所有操作都只"在"单个矩阵上;不再需要制作多个副本!(expo
函数中的1,1,1,0
助手除外;C++将自动删除该函数末尾的temp1
矩阵。
默认情况下,一个新的矩阵会用 1,1,1,0
初始化,因此可以删除 expo
和fib_matrix_expo
中的init
。
这也意味着您可以轻松扩展 Matrix
类以执行其他功能。
#include <cmath>
#include <iostream>
using namespace std;
class Matrix {
unsigned long long a_00;
unsigned long long a_01;
unsigned long long a_10;
unsigned long long a_11;
public:
Matrix();
void init(unsigned long long n);
void mult(Matrix* B);
void expo (unsigned int n);
unsigned long long value ()
{
return a_00;
}
};
unsigned long long fib_matrix_expo(unsigned int n);
int main() {
unsigned int n;
cin >> n;
unsigned long long result = fib_matrix_expo(n);
cout << result << endl;
return 0;
}
/* In this, and all other class functions, the specifier 'this->' is
not required. Per definition, all variables from the class are
immediately accessible. However, including 'this->..' makes it
clear you *are* modifying the class variables, and not local ones
with the same name */
Matrix::Matrix () {
this->a_00 = 1;
this->a_01 = 1;
this->a_10 = 1;
this->a_11 = 0;
}
void Matrix::init (unsigned long long n) {
this->a_00 = n;
this->a_01 = n;
this->a_10 = n;
this->a_11 = n;
}
void Matrix::mult(Matrix* B)
{
unsigned long long t00,t01,t10,t11;
t00 = this->a_00 * B->a_00 + this->a_01 * B->a_10;
t01 = this->a_00 * B->a_01 + this->a_01 * B->a_11;
t10 = this->a_10 * B->a_00 + this->a_11 * B->a_10;
t11 = this->a_10 * B->a_01 + this->a_11 * B->a_11;
this->a_00 = t00;
this->a_01 = t01;
this->a_10 = t10;
this->a_11 = t11;
// printf ("%llu %llu %llu %llun", a_00, a_01, a_10, a_11);
}
void Matrix::expo(unsigned int index)
{
if (index == 0)
{
this->init(1);
return;
}
if (index == 1)
{
return;
}
Matrix temp1;
// temp1 will initialize itself with (1,1,1,0),
// nothing more needed
while (--index > 0)
{
this->mult (&temp1);
}
}
unsigned long long fib_matrix_expo (unsigned int n)
{
Matrix base;
if (n == 0)
return 0;
// No need to initialize to the default values, as this
// is done in the default constructor.
base.expo(n-1);
return base.value();
// Since 'base' is a locally created class object, you
// do not need to delete it.
}
欢迎建设性的批评,因为我不是一个日常C++程序员;)
- 在某些循环内使用vector.push_back时出现分段错误
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 当我的阵列太大时出现分段错误
- 分段错误当我试图运行程序时出错
- 在c++中初始化矩阵时出现分段错误(核心转储)
- 尝试使用集合函数时出现分段错误
- 我无法缩小此分段错误的原因
- g++的分段错误(在NaN上使用to_string两次时)
- 我是如何在这段代码中出现分段错误的
- 创建结构的数组时遇到分段错误
- 在c++中键入向量中的所有值后,得到分段错误(核心转储)
- 在 c++ 中实现 Trie 时出现分段错误
- 为什么 fstream 在打开带有格式的文件时会导致分段错误?
- 为什么我遇到分段错误?
- 动态类的分段错误(家庭作业问题)
- 分段错误 - 读取初始化指针的数组
- 如何摆脱C ++中的分段错误错误?
- 使用 CTYPE 时出现分段错误
- 为什么代码给出分段错误?