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

C++向量与矩阵乘积程序处理非方阵时崩溃的问题排查

问题:非方阵输入导致矩阵乘积程序崩溃

实现了一个支持向量点积、矩阵-向量积、矩阵乘积的程序,处理向量和方阵时正常,但输入非方阵时崩溃,抛出以下异常:

terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check: __n (which is 1) >= this->size() (which is 1)

输入m 2 1 1 2 m 1 2 2 1时,程序在matrix_input函数中崩溃,无法输出error-2、error-3,怀疑是第二个矩阵的最后一行不存在导致问题。


程序代码

#include <iostream>
#include <vector>
#include <cassert>
using namespace std;

// 判断输入是向量还是矩阵
int m_or_v(char m_v) {
  if(m_v=='v')
    return 1;
  else if(m_v=='m')
    return 2;
  assert("error");
  return 0;
}

// 输入向量
void vector_input(vector<int> &vector_v) {
  int row = 0;
  cin >> row;
  int cache = 0;
  for(int i = 0;i<row;i++) {
    cin >> cache;
    vector_v.push_back(cache);
  }
}

// 输入矩阵
void matrix_input(vector<vector<int>> &matrix_m) {
  int row = 0;
  int col = 0;
  int cache_m = 0;
  cin >> row;
  cin >> col;
  for(int r = 0;r<row;r++) {
    vector<int> empty = {}; 
    cout << "error-1";
    for(int c = 0;c<col;c++) {
      cin >> cache_m;
      empty.push_back(cache_m);
      cout << "error-2";
    }
    matrix_m.push_back(empty);
  }
  cout << "error-3";
}

// 计算向量点积
void scalar_product(const vector<int> &vector_1,const vector<int> &vector_2) {
  int value = 0;
  if(vector_1.size()==vector_2.size()) {
    for(unsigned long i = 0;i<vector_1.size();i++) {
      value += (vector_1.at(i)*vector_2.at(i));
    }
    cout << "s" << endl;
    cout << value;
  }
  else 
    cout << "error";
}

// 判断运算类型(点积/矩阵-向量积/矩阵乘积)
int mult_mode(int mode1, int mode2) {
  if(mode1==1&&mode2==2) {
    cout << "error";
    return 0;
  }
  else if(mode1==1&&mode2==1)
    return 1;
  else if((mode1==2&&mode2==1)||(mode1==1&&mode2==2))
    return 2;
  else if(mode1==2&&mode2==2)
    return 3;
  else {
    cout << "error";
    return 0;
  }
}

// 检查矩阵-向量积是否合法
bool mvp_valid(const vector<vector<int>> &matrix_1, 
const vector<int> &vector_2) {
  if(matrix_1.at(0).size()==vector_2.size())
    return true;
  return false;
}

// 计算矩阵-向量积结果
void mvp_result(const vector<vector<int>> &matrix_1,
const vector<int> &vector_2, vector<int> &result) {
  int cache = 0;
  for(unsigned long row = 0;row<matrix_1.size();row++) {
    for(unsigned long col = 0;col<vector_2.size();col++) {
      cache += matrix_1.at(row).at(col)*vector_2.at(col);
    }
    result.push_back(cache);
    cache = 0;
  }
}

// 输出向量
void output_v(vector<int> &vec) {
  cout << "v " << vec.size() << endl;
  for(unsigned long i = 0;i<vec.size();i++) {
    cout << vec.at(i) << " ";
  }
}

// 检查矩阵乘积是否合法
bool mxm_valid(
const vector<vector<int>> &matrix_1,
const vector<vector<int>> &matrix_2) {
  if(matrix_1.at(0).size()==matrix_2.size())
    return true;
  return false;
}

// 计算矩阵乘积结果
void mxm_result(
const vector<vector<int>> &matrix_1,
const vector<vector<int>> &matrix_2, 
vector<vector<int>> &result_m) {
  
  int cache = 0;
  vector<int> empty;
  
  for(unsigned long row = 0;row<matrix_1.size();row++) {
    result_m.push_back(empty);
    for(unsigned long col = 0;col<matrix_2.at(row).size();col++) {
      for(unsigned long row_col = 0;row_col<matrix_2.size();row_col++) {
        cache+=matrix_1.at(row).at(row_col)*matrix_2.at(row_col).at(col);
      }
      result_m.at(row).push_back(cache);
      cache = 0;
    }
  }
}

// 输出矩阵
void output_m(const vector<vector<int>> &matx) {
  for(unsigned long col = 0;col<matx.size();col++) {
    for(unsigned long row = 0;row<matx.size();row++) {
      cout << matx.at(col).at(row) << " ";
    }
    cout << endl;
  }
}

// 输出矩阵尺寸
void size_m(const vector<vector<int>> &matx) {
  cout<<"m "<<matx.size()<<" "<<matx.at(0).size()<<endl;
}

int main() {
  
  char mode_c = ' ';
  int mode1 = 0;
  int mode2 = 0;
  vector<int> vector_1;
  vector<vector<int>> matrix_1;
  vector<int> vector_2;
  vector<vector<int>> matrix_2;
  
  // 输入第一个向量/矩阵
  cin >> mode_c;
  mode1 = m_or_v(mode_c);
  
  if(mode1==1) {
    vector_input(vector_1);  
  }
  else if(mode1==2) {
    matrix_input(matrix_1);
  }
  // 输入第二个向量/矩阵
  cin >> mode_c;
  mode2 = m_or_v(mode_c);
  
  if(mode2==1) {
    vector_input(vector_2);  
  }
  else if(mode2==2) {
    cout << "error-10";
    matrix_input(matrix_2);
    cout << "error-11";
  }

  switch(mult_mode(mode1, mode2)) {
    case 1:
      scalar_product(vector_1,vector_2);
      break;
    case 2:
      if(mvp_valid(matrix_1, vector_2)==true) {
        vector<int> result;
        mvp_result(matrix_1, vector_2, result);
        output_v(result);
      }
      else
        cout << "error";
      break;
    case 3:
      if(mxm_valid(matrix_1, matrix_2)==true) {
        vector<vector<int>> result_m;
        mxm_result(matrix_1, matrix_2, result_m);
        size_m(result_m);
        output_m(result_m);
      }
      else
        cout << "error";
      break;
  }
  
}

问题定位与修复

1. 矩阵乘法函数mxm_result的致命错误

崩溃的核心原因是mxm_result中遍历列时的逻辑错误:

for(unsigned long col = 0;col<matrix_2.at(row).size();col++)

这里用第一个矩阵的行索引row去访问第二个矩阵的行,当第一个矩阵行数(2)大于第二个矩阵行数(1)时,matrix_2.at(row)会触发越界(第二个矩阵只有索引0的行有效)。

修复方案:遍历第二个矩阵的列数,即matrix_2[0].size()(需先确保矩阵非空):

for(unsigned long col = 0; col < matrix_2.at(0).size(); col++)

2. 矩阵输出函数output_m的逻辑错误

原函数颠倒了行和列的遍历顺序,且错误用矩阵行数作为列的遍历范围,导致非方阵输出异常。

修复方案:正确遍历每一行,再遍历该行的所有列:

void output_m(const vector<vector<int>> &matx) {
  for(unsigned long row = 0; row < matx.size(); row++) {
    for(unsigned long col = 0; col < matx[row].size(); col++) {
      cout << matx[row][col] << " ";
    }
    cout << endl;
  }
}

3. 空矩阵的边界检查缺失

在mvp_valid、mxm_valid、size_m等函数中,直接访问matrix_1.at(0),若矩阵为空会触发越界。需先添加空矩阵检查:

bool mxm_valid(const vector<vector<int>> &matrix_1, const vector<vector<int>> &matrix_2) {
  if(matrix_1.empty() || matrix_2.empty()) return false;
  return matrix_1[0].size() == matrix_2.size();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 04:05:56