c++ 错误:地址0x0不是堆栈、malloc或(最近)释放的

hrirmatl  于 2023-02-26  发布在  其他
关注(0)|答案(1)|浏览(175)

我试图通过添加移动构造函数和移动赋值运算符来编写简单的程序。我正在使用valgrind检查内存泄漏。我面临着一些错误。我可以知道我在哪里犯了错误,以解决所有复制和移动构造函数以及赋值运算符没有任何内存泄漏的问题吗???我可以得到解决方案吗?

#include <iostream>
using namespace std;
class MY{
    int **p;
    public:
        MY(){
            cout << "Default Constructor" << endl;
            p = new int*[4];
            for(int i=0;i<4;i++)
                p[i] = new int[5];
        }
        // Copy Constructor
        MY(const MY& obj){
            cout << "Copy Constructor" << endl;
            p = new int*[4];
            for(int i=0;i<4;i++)
                p[i] = new int[5];

            for(int i=0;i<4;i++){
                for(int j=0;j<5;j++)
                    p[i][j] = obj.p[i][j];
            }
        }
        // Copy Assignment Operator
        MY& operator = (const MY & obj){
            cout << "Copy Assignment Opearator" << endl;

            if(this == &obj)
                return *this;

            for(int i=0;i<4;i++)
                delete [] p[i];
            delete [] p;

            p = new int*[4];
            for(int i=0;i<4;i++)
                p[i] = new int[5];

            for(int i=0;i<4;i++){
                for(int j=0;j<5;j++)
                    p[i][j] = obj.p[i][j];
            }
            return *this;
        }
        // Move Constructor
        MY(MY && obj){
            cout << "Move Constructor" << endl;
            p = obj.p;
            obj.p = nullptr;
        }
        // Move Assignment Operator
        MY& operator = (MY && obj){
            cout << "Move Assignement Operator" << endl;
            if(this == &obj)
                return *this;
            for(int i=0;i<4;i++)
                delete [] p[i];
            delete [] p;
            p = obj.p;
            obj.p = nullptr;

            return *this;
        }

        ~MY(){
            cout << "Destructor " << endl;
            for(int i=0;i<4;i++)
                delete [] p[i];
            delete [] p;    
        }
        void setData(){
            for(int i=0;i<4;i++){
                for(int j=0;j<5;j++)
                    p[i][j] = i*j;
            }
        }
        void printData(){
            for(int i=0;i<4;i++){
                for(int j=0;j<5;j++)
                    cout << p[i][j] << " ";
                cout << endl;    
            }
        }
};

int main()
{
    MY obj;
    obj.setData();
    obj.printData();

    // MY coj(obj);
    // coj.printData();

    // MY aoj ;
    // aoj = obj;
    // aoj.printData();

    MY moj(std::move(obj));
    moj.printData();

    MY loj;
    loj = std::move(obj);
    loj.printData();
}
zi8p0yeb

zi8p0yeb1#

移动构造函数和移动赋值运算符都将nullptr赋值给moved-from对象的p成员,该成员似乎处于无效状态。从对象移动必须使该对象保持有效状态。
由于对象处于无效状态,下一个方法调用将崩溃。在您的情况下,这可能是析构函数

~MY(){
        cout << "Destructor " << endl;
        for(int i=0;i<4;i++)
            delete [] p[i];  //crash because `p` is nullptr
        delete [] p;    
    }

一种解决方案是删除move-constructor,然后让move-assignment使用swap,这会使moved-from对象处于一种奇怪但有效的状态。

MY& operator = (MY && obj){
        cout << "Move Assignement Operator" << endl;
        std::swap(p, obj.p);
        return *this;
    }

另一种选择是重新设计类,使持有nullptr为有效状态。

=======

在没有答案的一面:
1.使用std::vector和std::array,您将永远不会再遇到这些问题。
1.你的复制构造函数太复杂了。它可以很简单

MY& operator = (const MY & obj){
     cout << "Copy Assignment Opearator" << endl;
     for(int i=0;i<4;i++){
         for(int j=0;j<5;j++)
             p[i][j] = obj.p[i][j];
     }
     return *this;
 }

相关问题