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

C++读取文件存储矩阵时退出返回值3221226356问题排查

问题描述

我尝试从文件读取输入内容,将其存储到自定义矩阵类的动态分配数组中。
每次运行代码时输入和输出结果均正确,但程序总是以返回值 3221226356 退出。
输入文件为.txt格式,首行标注矩阵行数、每行元素个数,文件内容示例如下:

10 15
000000000000000
000999000009900
000999000009900
000000900009900
000090000099900
000099900000000
090000900000000
099999999900000
000090090000000
000000000000000

其中10为矩阵总行数,15为每行的元素个数,需要读取矩阵并存入matArray成员,每个字符对应一个Element节点对象。
原始实现代码如下:

#include <bits/stdc++.h>
#include<iostream>
#include<fstream>
#include<string>
#include<cstring>


using namespace std;

class Element{
   
   private:
   char value;
   int processed;
   
   public:
   Element(){
      value = 0;
      processed = 0;
      
  }
   
   void setContent(char cellValue){ value = cellValue; }
   void setProcessed(int num1){ processed = num1; }
   char getContent(){ return value; }
   int getProcessed(){ return processed; }
};


class Matrix{

   private:
   Element* matArray;
   int rows; 
   int cols;

   public:
   Matrix(int nRows, int nCols){ 
   matArray = new Element[nRows * nCols];
   rows = nRows;
   cols = nCols;
   }

   void setInput(int r, int c, Element input){
      matArray[r * rows + c] = input;
   }

   Element getInput(int r, int c){ 
      return matArray[r * rows + c];
   }
   
};

int main(){
    
   int numRow = 0;
   int numCol = 0;
   string filename = "";
   
   string whiteSpace;
   string string1;
   
   cin >> filename;
   ifstream inFS;
   filename = filename + ".txt";
   inFS.open(filename.c_str());
   if(inFS.fail()){
      cout << "fail";
   }
   if(inFS.good()){
    cout << "good" << endl;
   }
   
   inFS >> numRow;
   inFS >> numCol;
   
   Matrix mat1(numRow, numCol);
   Element temp;
   char display;
   getline(inFS, whiteSpace);
   
//Reading the matrix from the file and inserting this information to mat1
    for(int i = 0; i < numRow; i++){
        getline(inFS, string1);
        cout << endl;
        for(int j = 0; j < numCol; j++){
           temp = mat1.getInput(i, j);
           temp.setContent(string1[j]);
           mat1.setInput(i, j, temp);      
           cout << mat1.getInput(i, j).getContent() << " ";
        }
    }
    
    cout << endl;
    
    return 0;
}
问题原因

返回值3221226356是Windows平台典型的堆损坏错误(对应十六进制码0xC0000374),说明程序运行过程中非法写入了堆内存,破坏了堆的管理结构,根源是代码存在两个核心问题:

  1. 矩阵索引计算逻辑错误
    二维数组映射到一维数组的正确索引公式是行号 * 列数 + 列号,但Matrix类的setInput和getInput方法里错写为r * rows + c(行号乘了行数而非列数)。
    当前10行15列的测试用例中,存和取都用了相同的错误索引,所以打印输出看起来正确,但实际内存布局完全混乱:当测试用例行数大于列数时,索引会直接超出matArray申请的内存边界,写入堆上的非法地址,破坏堆管理结构,最终在程序退出时触发错误。就算是当前10行15列的用例,错误的写入位置也可能覆盖堆块的校验填充字节,被堆检测机制捕获触发报错。
  2. Matrix类未正确管理动态内存
    用new[]申请了matArray的堆内存,但没有编写析构函数释放内存,存在内存泄漏;同时类没有自定义拷贝构造、拷贝赋值规则,后续如果发生对象拷贝会触发双重释放问题。
    另外还有健壮性缺陷:文件打开失败时只打印了"fail",没有终止程序,后续逻辑会继续操作无效的文件流,触发未定义行为。
修复方案
  • 修正索引计算公式,把setInput和getInput里的索引计算改为r * cols + c:
void setInput(int r, int c, Element input){
    matArray[r * cols + c] = input;
}

Element getInput(int r, int c){ 
    return matArray[r * cols + c];
}
  • 给Matrix类添加析构函数释放内存,同时禁用默认的浅拷贝逻辑避免双重释放,建议调整构造函数初始化顺序更规范:
class Matrix{
private:
    Element* matArray;
    int rows; 
    int cols;
public:
    Matrix(int nRows, int nCols){ 
        rows = nRows;
        cols = nCols;
        matArray = new Element[rows * cols];
    }
    // 新增析构函数
    ~Matrix() {
        delete[] matArray;
    }
    // 禁用浅拷贝
    Matrix(const Matrix&) = delete;
    Matrix& operator=(const Matrix&) = delete;

    // 其余方法修正索引后保持不变
    void setInput(int r, int c, Element input){
        matArray[r * cols + c] = input;
    }
    Element getInput(int r, int c){ 
        return matArray[r * cols + c];
    }
};
  • 文件打开失败时直接退出程序,不要继续执行后续逻辑:
if(inFS.fail()){
    cout << "fail to open file";
    return 1;
}
  • main函数中未使用的char display变量可以直接删除,属于冗余代码。

修复后程序即可正常运行,不会再出现异常退出的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 05:33:15