为啥这个核心转储错误发生在我的课堂上?我已经包含了复制构造函数、复制赋值和析构函数

Posted

技术标签:

【中文标题】为啥这个核心转储错误发生在我的课堂上?我已经包含了复制构造函数、复制赋值和析构函数【英文标题】:Why does this core dumped error happen in my class? I’ve already included copy constructor, copy assignment, and destructor为什么这个核心转储错误发生在我的课堂上?我已经包含了复制构造函数、复制赋值和析构函数 【发布时间】:2021-08-21 08:37:56 【问题描述】:

它只是一个二维数组(TwoD)类,它​​有一个构造函数来获取行数和列数,一个重载的赋值运算符和一个重载的非成员 + 运算符作为 TwoD 类的朋友。

更新代码:

#include<iostream>
using namespace std;
class TwoD
    public:
        TwoD()
        ~TwoD()
            for(int i=0;i<row;i++)
                delete [] arr[i];
            
            delete [] arr;
        
        TwoD(int r,int c):row(r),col(r)
            cout<<"Enter "<<r<<" rows of "<<c<<" doubles each"<<endl;
            arr=new double*[row];
            for(int i=0;i<r;i++)
                arr[i]=new double[c];
                for(int j=0;j<c;j++)
                    cin>>arr[i][j];
                
            
            
        
        TwoD(const TwoD& b)
            row=b.row;
            col=b.col;
            if(b.arr==NULL)
                return;
            
            arr=new double*[row];
            for(int i=0;i<row;i++)
                arr[i]=new double[col];
                for(int j=0;j<col;j++)
                    arr[i][j]=b.arr[i][j];
                
            
            
        
        void echo() const
            for(int i=0;i<row;i++)
                for(int j=0;j<col;j++)
                    cout<<arr[i][j]<<" ";
                
                cout<<endl;
            
        
        void set(int r,int c,double value)
            arr[r][c]=value;
        
        const TwoD& operator=(const TwoD& b);
        friend const TwoD operator+(const TwoD& a,const TwoD& b);
    private:
        int row,col;
        double** arr=NULL;
        
;

const TwoD& TwoD::operator=(const TwoD& b)
    if(this==&b)
        return *this;
    
    
    if(arr!=NULL)
        for(int i=0;i<row;i++)
            delete [] arr[i];
        
        delete [] arr;
    
    
    row=b.row;
    col=b.col;
    arr=new double*[row];
    for(int i=0;i<row;i++)
        arr[i]=new double[col];
        for(int j=0;j<col;j++)
            arr[i][j]=b.arr[i][j];
        
    
    return *this;


const TwoD operator+(const TwoD& a,const TwoD& b)
    TwoD temp(a);
    for(int i=0;i<a.row;i++)
        for(int j=0;j<a.col;j++)
            temp.arr[i][j]+=b.arr[i][j];
        
    
    return temp;

int main()
    cout<<"Enter the row and column dimensions of the array\n";
    int r,c;
    cin>>r>>c;
    TwoD a(r,c);
    cout<<"Echoing the 2 dim. array, matrix1\n";
    a.echo();

    cout<<"Enter the row and column dimensions of the array\n";
    cin>>r>>c;
    TwoD b(r,c);
    cout<<"Echoing the 2 dim. array, matrix2\n";
    b.echo();

    TwoD d;
    cout<<"Assigning matrix 2 to matrix 3\n";
    cout<<"Displaying the 2 dim array, matrix3 resulting from assignment"<<endl;
    d=b;
    cout<<"Rows "<<r<<" Cols "<<c<<endl;
    d.echo();

    cout<<"Displaying the 2 dim array, sum of matrix 1 and 2\n";
    cout<<"Rows "<<r<<" Cols "<<c<<endl;
    (a+b).echo();
    return 0;

旧的:

#include<iostream>
using namespace std;
class TwoD
    public:
        TwoD()
        ~TwoD()
            delete [] arr;
        
        TwoD(int r,int c):row(r),col(r)
            cout<<"Enter "<<r<<" rows of "<<c<<" doubles each"<<endl;
            arr=new double*[r];
            for(int i=0;i<r;i++)
                arr[i]=new double[c];
                for(int j=0;j<c;j++)
                    cin>>arr[i][j];
                
            
            
        
        TwoD(const TwoD& b)
            row=b.row;
            col=b.col;
            for(int i=0;i<row;i++)
                arr[i]=new double[col];
                for(int j=0;j<col;j++)
                    arr[i][j]=b.arr[i][j];
                
            
            
        
        void echo() const
            for(int i=0;i<row;i++)
                for(int j=0;j<col;j++)
                    cout<<arr[i][j]<<" ";
                
                cout<<endl;
            
        
        void set(int r,int c,double value)
            arr[r][c]=value;
        
        const TwoD operator=(const TwoD& b);
        friend const TwoD operator+(const TwoD& a,const TwoD& b);
    private:
        int row,col;
        double** arr;
        
;

const TwoD TwoD::operator=(const TwoD& b)
    if(this==&b)
        return *this;
    
    delete [] arr;
    row=b.row;
    col=b.col;
    arr=new double*[row];
    for(int i=0;i<row;i++)
        arr[i]=new double[col];
        for(int j=0;j<col;j++)
            arr[i][j]=b.arr[i][j];
        
    
    return *this;


const TwoD operator+(const TwoD& a,const TwoD& b)
    TwoD temp(a);
    for(int i=0;i<a.row;i++)
        for(int j=0;j<a.col;j++)
            temp.arr[i][j]+=b.arr[i][j];
        
    
    return temp;

int main()
    cout<<"Enter the row and column dimensions of the array\n";
    int r,c;
    cin>>r>>c;
    TwoD a(r,c);
    cout<<"Echoing the 2 dim. array, matrix1\n";
    a.echo();

    cout<<"Enter the row and column dimensions of the array\n";
    cin>>r>>c;
    TwoD b(r,c);
    cout<<"Echoing the 2 dim. array, matrix2\n";
    b.echo();

    TwoD d;
    cout<<"Assigning matrix 2 to matrix 3\n";
    cout<<"Displaying the 2 dim array, matrix3 resulting from assignment"<<endl;
    d=b;
    cout<<"Rows "<<r<<" Cols "<<c<<endl;
    d.echo();

    cout<<"Displaying the 2 dim array, sum of matrix 1 and 2\n";
    cout<<"Rows "<<r<<" Cols "<<c<<endl;
    (a+b).echo();
    return 0;

预期输出:

https://ibb.co/Csj5sH8

echo() 成员函数也是错误的(我不知道为什么),但我想先关注核心转储,这甚至意味着什么?

【问题讨论】:

delete [] arr 仅删除 arr 本身,即您使用 arr=new double*[r] 进行的分配。 arr 中的元素会泄漏 operator= 应该返回一个引用。否则每次赋值也会创建一个立即丢弃的副本,非常浪费。 所以这个 for(int i=0;i 【参考方案1】:

崩溃最有可能发生,因为在复制构造函数中您没有为 arr 本身分配内存。

当你这样做时,例如

arr[i]=new double[col];

那么变量arr未初始化的 并且将是无效的。这会调用未定义的行为,并可能导致崩溃。

你需要先为arr本身分配内存:

arr=new double*[row];

但是,还有另一个可能导致崩溃的原因,那是因为默认构造函数对象将具有未初始化的成员变量。

如果将这种默认构造的对象用作复制操作的源,那么您将使用这些未初始化的值,这将导致未定义的行为和可能的崩溃。

即使你正确初始化了变量,你也需要添加检查以确保你没有使用空指针等。

【讨论】:

哇,谢谢,请问为什么memeber函数echo()出错了?

以上是关于为啥这个核心转储错误发生在我的课堂上?我已经包含了复制构造函数、复制赋值和析构函数的主要内容,如果未能解决你的问题,请参考以下文章

为啥 STL 在 find 上映射核心转储?

为啥我的代码中出现分段错误(核心转储)错误?

为啥我的代码会出现分段/核心转储错误?

为啥我在 C 中收到警告“分段错误,核心转储”

在我的模板类示例中,出现“分段错误(核心转储)”错误

为啥我得到分段(核心转储)?