C++重载+运算符时出现malloc(): corrupted top size内存错误排查
问题描述
我正在编写一个用于矩阵基本运算的C++模板类,近一周来一直受内存问题困扰,每次调用构造函数似乎都会损坏对象。我怀疑+运算符重载存在问题,奇怪的是代码在2x2矩阵下正常运行,但更大的矩阵就会出错。
Matrix类代码
#include<iostream> #include<stdlib.h> #include <stdexcept> #include<cstring> using namespace std; template<class TypeData> class Matrix{ private: int Nrows , Ncols; TypeData *Array_Matrix; public: /*Constructors---------*/ Matrix(){ Nrows = 0; Ncols = 0; Array_Matrix = nullptr; } /*Constructor with 2 parameters:*/ Matrix(int _Nrows , int _Ncols){ this -> Nrows = _Nrows; this -> Ncols = _Ncols; Array_Matrix = new TypeData [Nrows * Ncols]; for(int i = 0 ; i<Nrows * Ncols ; i++){Array_Matrix[i] = 0.0;} } /*Copy constructor:*/ Matrix ( const Matrix &_M){ this -> Nrows = _M.Nrows ; this -> Ncols = _M.Ncols; Array_Matrix = new TypeData [Nrows * Ncols]; for(int i = 0 ; i<Nrows * Ncols ; i++){*(Array_Matrix + i) = *(_M.Array_Matrix + i);} } void Set_Value(int row , int col , TypeData value){ *(Array_Matrix + Ncols*row + col) = value;} /*---------------------------------------------------------------------------------------------------------------------*/ TypeData Get_Pos_Value(int row , int col){ if(row >= Nrows || col >= Ncols){throw std::invalid_argument( "Error!, index out of bounds!" );} else{return *(Array_Matrix + Ncols*row + col) ;}} TypeData *Get_Array(){ /*Method for returning a pointer to the "matrix"*/ return Array_Matrix;}; int Get_Nrows(){ return Nrows;} int Get_Ncols(){ return Ncols;} void Print_Matrix(){ for (int i = 0 ; i<Nrows ; i++){ cout<<endl; for (int j = 0 ; j<Ncols ; j++){ cout<<*(Array_Matrix + Ncols*i + j)<<" ";}}cout<<endl;} /*Operator overloading --------------------------------------------------------------------------------------------*/ Matrix operator = (const Matrix &Matrix_object){ delete [] Array_Matrix; this -> Nrows = Matrix_object.Nrows; this -> Ncols = Matrix_object.Ncols; Array_Matrix = new TypeData [Nrows * Ncols]; for (int i = 0 ; i<Nrows*Ncols ; i++){Array_Matrix [i] = Matrix_object.Array_Matrix[i];} return *this; } Matrix operator + (const Matrix &Matrix_object)const{ if(Matrix_object.Nrows != Nrows || Matrix_object.Ncols != Ncols) {throw std::invalid_argument("Different siex matrices cant be added!" );} Matrix <TypeData> Temp(0,0); Temp.Nrows = Nrows ; Temp.Ncols = Ncols; for(int i = 0 ; i<Nrows*Ncols; i++){ //Temp.Array_Matrix[i] = Array_Matrix[i] + Matrix_object.Array_Matrix[i]; *(Temp.Array_Matrix +i) = *(Array_Matrix +i) + *(Matrix_object.Array_Matrix + i);} return Temp;} Matrix operator - (const Matrix &Matrix_object)const{ if(Matrix_object.Nrows != Nrows || Matrix_object.Ncols != Ncols) {throw std::invalid_argument("Different size matrices can be substracted!" );} Matrix <TypeData> Temp(0,0); Temp.Nrows = Nrows ; Temp.Ncols = Ncols; for(int i = 0 ; i<Nrows*Ncols; i++){ //Temp.Array_Matrix[i] = Array_Matrix[i] - Matrix_object.Array_Matrix[i]; *(Temp.Array_Matrix +i) = *(Array_Matrix +i) - *(Matrix_object.Array_Matrix + i);} return Temp;} Matrix operator += (const TypeData num){ Matrix <TypeData> Temp(0,0); Temp.Nrows = Nrows ; Temp.Ncols = Ncols; for(int i = 0 ; i<Nrows*Ncols; i++){ Temp.Array_Matrix[i] = Array_Matrix[i] + num ;} return Temp;} Matrix operator -= (const TypeData num){ Matrix <TypeData> Temp(0,0); Temp.Nrows = Nrows ; Temp.Ncols = Ncols; for(int i = 0 ; i<Nrows*Ncols; i++){ Temp.Array_Matrix[i] = Array_Matrix[i]- num ;} return Temp;} ~Matrix(){ delete[] Array_Matrix;} };
Main函数代码
int main(){ int r1 , c1; cout<<"Matrix1: Enter Number of rows and columns "; cin>>r1>>c1; Matrix <float> My_Matrix(r1 , c1); for (int i = 0 ; i<My_Matrix.Get_Nrows() ; i++){ for (int j = 0 ; j<My_Matrix.Get_Ncols(); j++){ float value; cout<<"Type the value at: ["<<i<<"]["<<j<<"] position "; cin>>value; My_Matrix.Set_Value(i , j , value);}} int r2 , c2; cout<<"Matrix2: Enter Number of rows and columns "<<endl; cin>>r2>>c2; Matrix <float> My_Matrix2(r2,c2); for (int i = 0 ; i<My_Matrix2.Get_Nrows() ; i++){ for (int j = 0 ; j<My_Matrix2.Get_Ncols(); j++){ float value; cout<<"Type the value at: ["<<i<<"]["<<j<<"] position "; cin>>value; My_Matrix2.Set_Value(i , j , value);}} auto My_Matrix3 = My_Matrix + My_Matrix2; cout<<"Add: "<<endl; My_Matrix3.Print_Matrix(); cout<<endl; cout<<"Testing substraction: "<<endl; auto My_Matrix4 = My_Matrix - My_Matrix2; cout<<"Substraction is: "<<endl; My_Matrix4.Print_Matrix(); cout<<endl; cout<<"Testing = operator: "<<endl; My_Matrix4 = My_Matrix3; cout<<"Substraction matriz is now: "<<endl; My_Matrix4.Print_Matrix(); cout<<endl<<"as the Add matrix! "<<endl; cout<<"Testing +=:"<<endl; int num ; cout<<"Please enter an integer number: ";cin>>num; (My_Matrix4 += num).Print_Matrix(); return 0;}
问题分析与修复
核心错误
你代码中的operator+、operator-、operator+=、operator-=存在致命内存问题:
- 创建
Temp(0,0)时,Array_Matrix是默认构造的nullptr - 直接修改
Temp的行列数但未分配内存,随后访问Temp.Array_Matrix属于空指针解引用,是未定义行为 - 2x2矩阵时可能恰好未触发崩溃,但大矩阵会覆盖更多非法内存,导致对象损坏
此外还有两个次要问题:
operator=未处理自赋值,若对象赋值给自己,delete[]后会访问已释放的内存operator+=/operator-=语义错误:这类运算符应修改当前对象而非返回新临时对象
修复后的关键代码
// 修复operator+:直接创建对应大小的临时矩阵 Matrix operator + (const Matrix &Matrix_object)const{ if(Matrix_object.Nrows != Nrows || Matrix_object.Ncols != Ncols) {throw std::invalid_argument("Different size matrices can't be added!" );} Matrix <TypeData> Temp(Nrows, Ncols); for(int i = 0 ; i<Nrows*Ncols; i++){ Temp.Array_Matrix[i] = Array_Matrix[i] + Matrix_object.Array_Matrix[i]; } return Temp; } // 修复operator-:同operator+逻辑 Matrix operator - (const Matrix &Matrix_object)const{ if(Matrix_object.Nrows != Nrows || Matrix_object.Ncols != Ncols) {throw std::invalid_argument("Different size matrices can't be subtracted!" );} Matrix <TypeData> Temp(Nrows, Ncols); for(int i = 0 ; i<Nrows*Ncols; i++){ Temp.Array_Matrix[i] = Array_Matrix[i] - Matrix_object.Array_Matrix[i]; } return Temp; } // 修复operator+=:修改当前对象,返回引用 Matrix& operator += (const TypeData num){ for(int i = 0 ; i<Nrows*Ncols; i++){ Array_Matrix[i] += num; } return *this; } // 修复operator-=:同operator+=逻辑 Matrix& operator -= (const TypeData num){ for(int i = 0 ; i<Nrows*Ncols; i++){ Array_Matrix[i] -= num; } return *this; } // 修复operator=:增加自赋值检查 Matrix& operator = (const Matrix &Matrix_object){ if(this == &Matrix_object){ return *this; } delete [] Array_Matrix; this -> Nrows = Matrix_object.Nrows; this -> Ncols = Matrix_object.Ncols; Array_Matrix = new TypeData [Nrows * Ncols]; for (int i = 0 ; i<Nrows*Ncols ; i++){ Array_Matrix[i] = Matrix_object.Array_Matrix[i]; } return *this; }
修复说明
- 运算符+/-:调用带参数的构造函数创建对应大小的临时矩阵,确保内存已分配
- 运算符+=/-=:遵循C++标准语义,直接修改当前对象并返回自身引用,符合用户预期
- 赋值运算符:增加自赋值检查,避免释放自身内存后访问非法地址
额外优化建议
- 用
std::copy替代手动循环复制元素(需包含<algorithm>),代码更简洁高效:std::copy(_M.Array_Matrix, _M.Array_Matrix + Nrows*Ncols, Array_Matrix); - 构造函数初始化内存时,用
new TypeData[Nrows*Ncols]()(加括号)实现值初始化,对复杂类型更安全 - 避免在头文件中使用
using namespace std;,防止命名冲突
内容的提问来源于stack exchange,提问作者JFCastello
相关产品推荐
相关产品推荐

