双重免费或腐败...但为什么? [英] Double free or corruption...but why?

查看:180
本文介绍了双重免费或腐败...但为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#include <queue>
using namespace std;

class Test{
    int *myArray;

        public:
    Test(){
        myArray = new int[10];
    }

    ~Test(){
        delete[] myArray;
    }

};


int main(){
    queue<Test> q
    Test t;
    q.push(t);
}

运行此操作后,我得到一个运行时错误double free or corruption 。如果我摆脱析构函数内容( delete )它工作正常。有什么问题?

After I run this, I get a runtime error "double free or corruption". If I get rid of the destructor content (the delete) it works fine. What's wrong?

推荐答案

让我们谈谈在C ++中复制对象。



Test t; 调用默认构造函数,它分配一个新的整数数组。

Let's talk about copying objects in C++.

Test t;, calls the default constructor, which allocates a new array of integers. This is fine, and your expected behavior.

当您使用<$ c> t $ c> q.push(t)。如果你熟悉Java,C#或几乎任何其他面向对象的语言,你可能希望你创建的对象被添加到队列,但C ++不工作这样。

Trouble comes when you push t into your queue using q.push(t). If you're familiar with Java, C#, or almost any other object-oriented language, you might expect the object you created earler to be added to the queue, but C++ doesn't work that way.

当我们来看看 std :: queue: :push 方法,我们看到添加到队列的元素是初始化为x的副本。它实际上是一个全新的对象,使用复制构造函数复制您的原始测试对象的每个成员,以创建一个新的测试

When we take a look at std::queue::push method, we see that the element that gets added to the queue is "initialized to a copy of x." It's actually a brand new object that uses the copy constructor to duplicate every member of your original Test object to make a new Test.

您的C ++编译器会默认为您生成一个复制构造函数!这很方便,但导致指针成员的问题。在你的例子中,记住 int * myArray 只是一个内存地址;当 myArray 的值从旧对象复制到新对象时,现在将有两个对象指向内存中的同一个数组。这不是本质上坏,但析构函数将尝试删除相同的数组两次,因此双重自由或损坏运行时错误。

Your C++ compiler generates a copy constructor for you by default! That's pretty handy, but causes problems with pointer members. In your example, remember that int *myArray is just a memory address; when the value of myArray is copied from the old object to the new one, you'll now have two objects pointing to the same array in memory. This isn't intrinsically bad, but the destructor will then try to delete the same array twice, hence the "double free or corruption" runtime error.

第一步是实现一个复制构造函数,它可以安全地将数据从一个对象复制到另一个对象。为了简单起见,它可以看起来像这样:

The first step is to implement a copy constructor, which can safely copy the data from one object to another. For simplicity, it could look something like this:

Test(const Test& other){
    myArray = new int[10];
    memcpy( myArray, other.myArray, 10 );
}



现在,当您复制Test对象时,新对象和数组的值也将被复制。

Now when you're copying Test objects, a new array will be allocated for the new object, and the values of the array will be copied as well.

我们还没有完全解决问题。还有一种编译器为您生成的可能导致类似问题的方法 - 赋值。区别在于,使用赋值,我们已经有一个现有的对象,其内存需要被适当地管理。下面是一个基本的赋值运算符实现:

We're not completely out trouble yet, though. There's another method that the compiler generates for you that could lead to similar problems - assignment. The difference is that with assignment, we already have an existing object whose memory needs to be managed appropriately. Here's a basic assignment operator implementation:

Test& operator= (const Test& other){
    if (this != &other) {
        memcpy( myArray, other.myArray, 10 );
    }
    return *this;
}

这里的重要部分是我们从其他数组复制数据进入这个对象的数组,保持每个对象的内存分离。我们还有自我分配的检查;否则,我们会从自己复制到自己,这可能会抛出一个错误(不知道它应该做什么)。如果我们删除并分配更多内存,则自我分配检查会阻止我们删除需要复制的内存。

The important part here is that we're copying the data from the other array into this object's array, keeping each object's memory separate. We also have a check for self-assignment; otherwise, we'd be copying from ourselves to ourselves, which may throw an error (not sure what it's supposed to do). If we were deleting and allocating more memory, the self-assignment check prevents us from deleting memory from which we need to copy.

这篇关于双重免费或腐败...但为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆