为啥我在尝试将元素添加到 vector<vector<int>>(矩阵实现)时出现段错误?

Posted

技术标签:

【中文标题】为啥我在尝试将元素添加到 vector<vector<int>>(矩阵实现)时出现段错误?【英文标题】:Why am I getting a segfault trying to add element to vector<vector<int>>(matrix implementation)?为什么我在尝试将元素添加到 vector<vector<int>>(矩阵实现)时出现段错误? 【发布时间】:2015-12-21 01:00:08 【问题描述】:

我在下面包含了对我的 C++ 程序的描述,但我觉得这个问题可能太基本了,所以没有必要描述。本质上,我的“parse_matrix”方法出现了段错误。我已经进行了一些调试并标记了运行结束的行,但我无法弄清楚到底出了什么问题。我正在尝试做的是使用 cin 从输入文件中获取一个数字并将其放入索引 [i][j] 处的矩阵(实现为向量>)。我尝试了不同的方法来设置矩阵中的值(首先

这是程序说明:

我正在编写一个程序,该程序基本上将获取一个包含矩阵信息和要执行的操作的输入文件,并将输出结果矩阵。输入文件的第一行会说“加法”或“乘法”,第二行会说有多少矩阵。然后,每个矩阵将有两行,第一行有两个数字,由空格分隔,确定后续矩阵的维度(行列),其内容将写在一行中并分组为行(所以一个 2x2 矩阵将是 A(1,1) A(1,2) A(2,1) A(2,2) (1,1 是左上角,1,2 是右上角,2,1 是左下角,2,2 是右下角)。

一个示例输入文件,它告诉程序添加 3 个矩阵,所有维度均为 2x2:

add                                                                      
3
2 2
1 2 3 4
2 2
1 1 1 1
2 2 
1 0 1 0

这是我的代码(我已经标记了问题似乎发生的位置)。任何帮助将不胜感激!

#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;

//define dot product
int dot(vector<int> a, vector<int> b)
    int c=0;
    int size = a.size();
    for (int i=0; i<size; i++)
        c += a[i]*b[i];
    
    return c;


//define Matrix struct
struct Matrix 
    vector<vector<int>> mtrx;
    int m;
    int n;

    //overloading "+" for adding matrices
    Matrix operator+ (const Matrix& b)
        Matrix c;
        for (int i=0; i<b.m; i++)
            for (int j=0; j<b.n; j++)

                c.mtrx[i][j] = this->mtrx[i][j] + b.mtrx[i][j];
            
        
        return c;
    

    //overloading "*" for multiplying matrices
    Matrix operator* (const Matrix& b)
        Matrix c;
        for (int i=0; i<b.m; i++)
            for (int j=0; j<b.n; j++)
                vector<int> temp;
                for (int k=0; k<b.m; k++)
                    temp.push_back(b.mtrx[k][j]);
                
                c.mtrx[i][j] = dot(this->mtrx[i],temp);
            
        
        c.n = b.n;
        return c;
    

;

//will apply the designated operation to two matrices
Matrix operation(Matrix a, Matrix b, string op_type)
    Matrix c;
    if (op_type=="add")
        if (a.m == b.m && a.n == b.n) 
            c = a+b;
        
        else 
            cout<<"Dimensions do not match. Addition cannot be performed.";
            exit(1);
        
    
    else if (op_type == "multiply")
        if (a.n == b.m)
            c = a*b;
        
        else 
            cout<<"Inner dimensions do not match. Multiplication cannot be performed.";
            exit(1);
        
    
    else 
        cout<<"This program does not "<<op_type<<" matrices. It only adds or multiplies.";
        exit(1);
    
    return c;


//reads line and sets matrix elements
void parse_matrix(Matrix *p)
    int m,n;
    cin>>m>>n;

    p->m = m;
    p->n = n;

    for (int i=0; i<m; i++) 
        for (int j=0; j<n; j++)
             int x;
             cin>>x;
/************THIS IS WHERE THE SEGFAULT OCCURS***************/
             ((p->mtrx)[i]).push_back(x);
        
    


//prints matrix elements in a line (row, column) lexicographical ordering      using cout 
void print_matrix(Matrix matrix)
    int m = matrix.m;
    int n = matrix.n;

    for (int i=0; i<m; i++) 
        for (int j=0; j<n; j++)
            cout<<matrix.mtrx[i][j];
        
        cout<<endl;

    


//main will read in type of operation, number of matrices, and individual matrices
//each matrix resides on a line, and will be parsed into rows and columns
//each matrix line will be preceded by a line of two ints that specifies the matrix dimensions
int main() 

    string op_type;
    cin>>op_type;
    int num;
    cin>>num;

    Matrix matrix;
    Matrix final;

    parse_matrix(&final);

    for (int k=1; k<num; k++) 
        parse_matrix(&matrix);
        operation(final, matrix, op_type);
    

    print_matrix(final);

    return 0;

【问题讨论】:

temp 中的parse_matrix 是什么?据我所知,它是一个未初始化的变量,代码不可能出现段错误,因为它甚至不编译,更不用说运行了。 这段代码有很多问题。您可以通过正确初始化 Matrix 变量来开始修复它们。你现在拥有它的方式是向量是空的,当你尝试访问它们时你会崩溃。 【参考方案1】:

这段代码有问题:

Matrix c;
...
c.mtrx[i][j] =

这访问越界。 c.mtrx 被创建为 0x0 矩阵,但您尝试访问索引 i,j[] 运算符不会自动扩展向量的大小。

您标记的行可能有同样的问题:

((temp.mtrx)[i]).push_back(x);

您的代码没有显示 temp 是什么,但它可能是一个全局变量,还没有 i 那么多行。

相反,您需要确保索引[i] 处的向量条目已经存在,然后再尝试写入其值。您可以使用push_back 作为替代。

【讨论】:

但在我的 for 循环中,i 最初为 0。如果我声明一个 vector 而不明确设置其内容,它仍然会在 [0] 处有一个元素,对吗? 好吧,我不知道我为什么这么想,只是测试了一下,显然向量完全是空的。数组也一样吗?我认为我的困惑来自这样一个事实,即我知道数组的值本质上是指向其第一个条目的指针,然后指向下一个条目,依此类推。我知道向量元素不是连续存储的。那么向量是如何开始的呢? 您可以使用resize 函数来调整向量的大小。或者您可以在构造函数中指定大小。您需要为每一行执行此操作。 C 样式数组不可调整大小,所以我不确定您在说什么。 operator+ 函数的示例:Matrix c( b.m, vector&lt;int&gt;(b.n) );。虽然在这种情况下Matrix c = b; 会更简单,然后在下面的代码中使用+= 而不是+。对于 operator* 函数,您需要进行一些重新设计 - 您尝试写入值,然后在最后更改尺寸,但这是行不通的。

以上是关于为啥我在尝试将元素添加到 vector<vector<int>>(矩阵实现)时出现段错误?的主要内容,如果未能解决你的问题,请参考以下文章

为啥合并打印顺序相反

为啥基于范围的 for 循环不修改容器元素?

如何将元素添加到指针向量中?

不能将结构类型的元素添加到向量?

为啥 make_unique to vector::back() 创建另一个副本?

为啥 'std::vector<int> b2;'创建一个 1 元素向量,而不是 2 元素向量?