【问题标题】:Error : Address 0x0 is not stack'd, malloc'd or (recently) free'd错误:地址 0x0 没有被堆栈、malloc 或(最近)释放
【发布时间】:2023-02-23 02:24:20
【问题描述】:

我试图通过添加移动构造函数和移动赋值运算符来编写简单的程序。我正在使用 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();
}

【问题讨论】:

  • 您正在尝试取消引用或删除空指针
  • 如果任何分配失败,MY() 就会出现理论上的泄漏,但我怀疑这是你的问题。
  • @jabaa——删除一个空指针是可以的。
  • 在你的析构函数中,你在循环中调用 delete p[i],如果 p 有效,这很好,但如果 p 为 NULL,那么这是对 NULL 指针的取消引用的尝试,你会(希望)崩溃.

标签: c++


【解决方案1】:

您的移动构造函数和移动赋值运算符都将 nullptr 分配给移出对象的 p 成员,这似乎是无效状态。从对象移动必须使该对象处于有效状态。

由于该对象处于无效状态,因此对它的下一个方法调用将崩溃。在你的情况下,这可能是析构函数

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

最简单的解决方案是交换,这会使移出的对象处于奇怪但有效的状态。

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

============

在事物的非答案方面:

  1. 使用 std::vector 和 std::array,您将再也不会遇到这些问题。

  2. 您的复制构造函数过于复杂。它可以很简单

     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;
     }
    

【讨论】:

  • 我同意 std::swap 选项,但从移动赋值运算符函数中删除删除操作会导致更多内存泄漏。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-07
  • 1970-01-01
  • 2017-09-13
  • 2018-10-12
  • 1970-01-01
  • 2019-08-21
  • 1970-01-01
相关资源
最近更新 更多