小的ref-counting缓冲类中的内存损坏

时间:2011-10-19 22:25:09

标签: c++

我有一个简单的引用计数类,它包含一个内存缓冲区。它看起来像这样:

#include <algorithm>

template<typename T>
struct buffer
{
    // create a buffer of length n
    buffer(unsigned n) : rc(*(new unsigned(1))), data(new T[n]) { }

    buffer(const buffer<T> & rhs) : rc(++rhs.rc), data(rhs.data) { }

    buffer<T>& operator=(buffer<T> rhs)
    {
        std::swap(rc, rhs.rc);
        std::swap(data, rhs.data);
        return *this;
    }

    ~buffer()
    {
        if (--rc == 0) {
            delete [] data;
            delete (&rc);
        }
    }

private:
    mutable unsigned & rc;
    T * data;
};


int main() {
    typedef buffer<int> numbers;
    numbers n1(10);
    numbers n2(20);
    numbers n3(30);
    n1 = n2 = n3 = n2;
}

我没有看到代码有任何问题。但Visual Studio和valgrind抱怨内存损坏。

我现在盯着这段代码已经太久了。有人能发现错误吗?

1 个答案:

答案 0 :(得分:13)

一个问题是当你swap(rc, rhs.rc);实际上是在交换重新计算的内容而不是参考文献。

想象一下你有这种情况:

Before

当您swap(rc, rhs.rc);时,对引用计数的引用将保持不变,并且计数本身将交换。这是你在两次掉期后得到的结果:

After

缓冲区指针是正确的,但对引用计数的引用仍然引用相同的unsigned对象。但是交换了这些对象的值。注意缓冲区B在从其中一个交换对象看到时如何引用refcount 2,并从底部看到它时引用引用1。

你需要使用refcount的指针,并交换指针,而不是内容。